iOS
...
Data Objects
iOS ParseSwift 관계형 데이터 쿼리 구현 가이드
12 분
관계형 쿼리 소개 이 이전 가이드 https //www back4app com/docs/ios/parse swift sdk/data objects/query cookbook 에서는 back4app 데이터베이스에서 다양한 쿼리를 수행하는 방법에 대해 자세히 설명했습니다 이 가이드에서는 관계가 있는 객체와 관련된 특정 유형의 쿼리에 중점을 둡니다 전제 조건 이 튜토리얼을 완료하려면 다음이 필요합니다 back4app에서 생성된 앱 쿼리를 테스트할 기본 ios 앱 목표 back4app 데이터베이스에 저장된 관계형 데이터를 쿼리하기 위해 parseswift sdk parseswift sdk 를 사용합니다 1 query\<u> 클래스에 대한 간단한 리뷰 back4app 데이터베이스에서 수행되는 모든 쿼리는 일반 클래스 query\<u> query\<u> 일반 매개변수 u u ( parseobject parseobject 프로토콜을 준수) 는 우리가 데이터베이스에서 검색하려는 객체의 데이터 유형입니다 myobject myobject , 우리는 다음과 같은 방법으로 back4app 데이터베이스에서 이러한 객체를 검색합니다 1 import parseswift 2 3 struct myobject parseobject { 4 5 } 6 7 let query = myobject query() 8 9 // executes the query asynchronously 10 query find { result in 11 // handle the result (of type result<\[myobject], parseerror>) 12 } query\<u> query\<u> 클래스에 대한 자세한 내용은 공식 문서에서 확인하세요 https //github com/parse community/parse swift 2 back4app 데이터베이스에 데이터 저장하기 쿼리를 실행하기 전에 back4app 데이터베이스에 일부 데이터를 설정하는 것이 필요합니다 우리는 다섯 가지 유형의 객체를 저장할 것입니다 author 1 struct author parseobject { 2 3 var name string? 4 } book 1 struct book parseobject { 2 3 var title string? 4 var publisher publisher? 5 var publishingdate date? 6 } isbd 1 struct isbd parseobject { 2 3 var isbn string? 4 var book pointer\<book>? 5 } publisher 1 struct publisher parseobject { 2 3 var name string? 4 } bookstore 1 struct bookstore parseobject { 2 3 var name string? 4 } 또한 관계형 데이터를 위한 쿼리를 구성하기 위해 다음과 같은 관계를 구현할 것입니다 1 1 관계 도서 도서 와 isbd isbd 1\ n 관계 도서 도서 와 출판사 출판사 m\ n 관계 도서 도서 와 저자 저자 m\ n 관계 서점 서점 와 도서 도서 이제 back4app 데이터베이스에 일부 데이터를 저장하는 절차를 진행합니다 이 단계는 swift swift 또는 back4app 플랫폼의 앱 콘솔에서 직접 구현할 수 있습니다 swift //after setting up your xcode project, calling the following method should save some sample data on your back4app database 1 import parseswift 2 3 func savesampledata() { 4 do { 5 // authors 6 let aaronwriter = try author(name "aaron writer") save() 7 let beatricenovelist = try author(name "beatrice novelist") save() 8 let caseycolumnist = try author(name "casey columnist") save() 9 10 // publishers 11 let acaciapublishings = try publisher(name "acacia publishings") save() 12 let birchdistributions = try publisher(name "birch distributions") save() 13 14 // books with their corresponding isbd 15 let alovestorybook = try book( 16 title "a love story", 17 publisher acaciapublishings, 18 publishingdate date(string "05/07/1998") 19 ) save() 20 relation? add("authors", objects \[aaronwriter]) save() // establishes the m\ n relatin between book and author 21 22 // fetches the isbd associated to alovestorybook and establishes the 1 1 relation 23 if let book = alovestorybook, var isbd = try book fetch(includekeys \["isbd"]) isbd { 24 isbd book = try pointer\<book>(book) 25 = try isbd save() 26 } else { 27 fatalerror() 28 } 29 30 let benevolentelvesbook = try book( 31 title "benevolent elves", 32 publisher birchdistributions, 33 publishingdate date(string "11/30/2008") 34 ) save() 35 relation? add("authors", objects \[beatricenovelist]) save() // establishes the m\ n relatin between book and author 36 37 // fetches the isbd associated to benevolentelvesbook and establishes the 1 1 relation 38 if let book = benevolentelvesbook, var isbd = try book fetch(includekeys \["isbd"]) isbd { 39 isbd book = try pointer\<book>(book) 40 = try isbd save() 41 } else { 42 fatalerror() 43 } 44 45 let canyoubelieveitbook = try book( 46 title "can you believe it", 47 publisher birchdistributions, 48 publishingdate date(string "08/21/2018") 49 ) save() 50 relation? add("authors", objects \[aaronwriter, caseycolumnist]) save() // establishes the m\ n relatin between book and author 51 52 // fetches the isbd associated to canyoubelieveitbook and establishes the 1 1 relation 53 if let book = canyoubelieveitbook, var isbd = try book fetch(includekeys \["isbd"]) isbd { 54 isbd book = try pointer\<book>(book) 55 = try isbd save() 56 } else { 57 fatalerror() 58 } 59 60 // book store 61 guard let safealovestorybook = alovestorybook, 62 let safebenevolentelvesbook = benevolentelvesbook, 63 let safecanyoubelieveitbook = canyoubelieveitbook 64 else { 65 throw nserror( 66 domain bundle main description, 67 code 0, 68 userinfo \[nslocalizeddescriptionkey "failed to unwrapp stored books "] 69 ) 70 } 71 72 // saves the stores together with their 1\ n relation with book's 73 let booksoflove = try bookstore(name "books of love") save() 74 = try booksoflove relation? add("books", objects \[safealovestorybook]) save() 75 76 let fantasybooks = try bookstore(name "fantasy books") save() 77 = try fantasybooks relation? add("books", objects \[safebenevolentelvesbook]) save() 78 79 let generalbooks = try bookstore(name "general books") save() 80 = try generalbooks relation? add("books", objects \[safealovestorybook, safecanyoubelieveitbook]) save() 81 82 } catch let error as parseerror { 83 print("error \n", error message) 84 } catch { 85 print("error \n", error localizeddescription) 86 } 87 } back4app's console //a quick way to insert elements on your back4app database is via the console located in your app’s api section once you are there, you can start running javascript code to save the sample data 1 // authors 2 const aaronwriter = new parse object('author'); 3 aaronwriter set('name', 'aaron writer'); 4 await aaronwriter save(); 5 6 const beatricenovelist = new parse object('author'); 7 beatricenovelist set('name', 'beatrice novelist'); 8 await beatricenovelist save(); 9 10 const caseycolumnist = new parse object('author'); 11 caseycolumnist set('name', 'casey columnist'); 12 await caseycolumnist save(); 13 14 // publishers 15 const acaciapublishings = new parse object('publisher'); 16 acaciapublishings set('name', 'acacia publishings'); 17 await acaciapublishings save(); 18 19 const birchdistributions = new parse object('publisher'); 20 birchdistributions set('name', 'birch distributions'); 21 await birchdistributions save(); 22 23 // books with their corresponding isbd 24 const alovestoryisbd = new parse object('isbd'); 25 alovestoryisbd set('isbn', '9781401211868'); 26 await alovestoryisbd save(); 27 28 const alovestorybook = new parse object('book'); 29 alovestorybook set('title', 'a love story'); 30 alovestorybook set('publisher', acaciapublishings); 31 alovestorybook set('publishingdate', new date('05/07/1998')); 32 alovestorybook set('isbd', alovestoryisbd); 33 const bookarelation = alovestorybook relation("authors"); 34 bookarelation add(aaronwriter); 35 await alovestorybook save(); 36 alovestoryisbd set('book', alovestorybook topointer()); 37 await alovestoryisbd save(); 38 39 const benevolentelvesisbd = new parse object('isbd'); 40 benevolentelvesisbd set('isbn', '9781401211868'); 41 await benevolentelvesisbd save(); 42 43 const benevolentelvesbook = new parse object('book'); 44 benevolentelvesbook set('title', 'benevolent elves'); 45 benevolentelvesbook set('publisher', birchdistributions); 46 benevolentelvesbook set('publishingdate', new date('11/31/2008')); 47 benevolentelvesbook set('isbd', benevolentelvesisbd); 48 const bookbrelation = benevolentelvesbook relation("authors"); 49 bookbrelation add(beatricenovelist); 50 await benevolentelvesbook save(); 51 benevolentelvesisbd set('book', benevolentelvesbook topointer()); 52 await benevolentelvesisbd save(); 53 54 const canyoubelieveitisbd = new parse object('isbd'); 55 canyoubelieveitisbd set('isbn', '9781401211868'); 56 await canyoubelieveitisbd save(); 57 58 const canyoubelieveitbook = new parse object('book'); 59 canyoubelieveitbook set('title', 'can you believe it?'); 60 canyoubelieveitbook set('publisher', birchdistributions); 61 canyoubelieveitbook set('publishingdate', new date('08/21/2018')); 62 canyoubelieveitbook set('isbd', canyoubelieveitisbd); 63 const bookcrelation = canyoubelieveitbook relation("authors"); 64 bookcrelation add(aaronwriter); 65 bookcrelation add(caseycolumnist); 66 await canyoubelieveitbook save(); 67 canyoubelieveitisbd set('book', canyoubelieveitbook topointer()); 68 await canyoubelieveitisbd save(); 69 70 // book store 71 const booksoflovestore = new parse object('bookstore'); 72 booksoflovestore set('name', 'books of love'); 73 const bookstorearelation = booksoflovestore relation("books"); 74 bookstorearelation add(alovestorybook); 75 await booksoflovestore save(); 76 77 const fantasybooksstore = new parse object('bookstore'); 78 fantasybooksstore set('name', 'fantasy books'); 79 const bookstorebrelation = fantasybooksstore relation("books"); 80 bookstorebrelation add(benevolentelvesbook); 81 await fantasybooksstore save(); 82 83 const generalbooksstore = new parse object('bookstore'); 84 generalbooksstore set('name', 'general books'); 85 const bookstorecrelation = generalbooksstore relation("books"); 86 bookstorecrelation add(alovestorybook); 87 bookstorecrelation add(canyoubelieveitbook); 88 await generalbooksstore save(); 3 데이터 쿼리하기 데이터베이스에 작업할 샘플 데이터가 준비되면, 우리는 앞서 자세히 설명한 관계와 관련된 다양한 종류의 쿼리를 실행하기 시작합니다 1 1 관계가 포함된 쿼리 두 개의 데이터 유형이 1 1 관계를 공유하는 경우 ( 책 책 와 isbd isbd 가 이 경우에 해당합니다), 우리는 다음과 같이 서로를 검색할 수 있습니다 책 책 에서 관계를 구현한 방식은 관련된 isbd isbd 객체를 단순히 쿼리에서 include( ) include( ) 메서드를 호출하여 검색할 수 있게 해줍니다 이제 책 a love story 에서 isbd isbd 를 검색해 보겠습니다 1 let alovestorybookquery = book query("title" == "a love story") include("isbd") // note how we include the isbd with the include( ) method 2 3 let book = try? alovestorybookquery first() // retrieves synchronously the book including its isbd 4 5 alovestorybookquery first { result in // retrieves asynchronously the book including its isbd 6 // handle the result (of type result\<book, parseerror>) 7 } 반면, 주어진 isbd isbd 와 관련된 책 책 객체를 검색하는 쿼리는 다음과 같이 구현됩니다 isbd isbd 의 구현을 살펴보면, 관계가 책 책 속성 (타입 pointer<책> pointer<책> )로 표현된다는 것을 알 수 있습니다 이 포인터는 가리키는 객체에 대한 정보를 검색하기 위한 메서드와 속성 세트를 제공합니다 특히, 우리는 fetch( ) fetch( ) 메서드를 책 책 속성에서 호출하여 관련된 책 책 1 let someisbd isbd 2 3 let book book? = try? someisbd book? fetch() // retrieves synchronously the book asscociated to someisbd 4 5 someisbd book? fetch { result in // retrieves asynchronously the book asscociated to someisbd 6 // handle the result (of type result\<book, parseerror>) 7 } 우리는 1 1 관계에 대한 이 구현이 유일하지 않다는 점을 언급해야 합니다 사용 사례에 따라 1 1 관계를 다양한 방식으로 구현할 수 있습니다 1\ n 관계를 포함하는 쿼리 특정 출판사가 발행한 모든 책을 쿼리해야 하는 시나리오에서는 먼저 출판사를 검색해야 합니다 예를 들어, 우리는 먼저 출판사 acacia publishings 와 관련된 데이터 객체를 검색합니다 상황에 따라 이 과정은 다를 수 있습니다 1 do { 2 // using the object's objectid 3 let acaciapublishings = try publisher(objectid "some object id") fetch() 4 5 // or 6 // using a query 7 let acaciapublishings = try publisher query("name" == "acacia publishings") first() // returns (synchronously) the first publisher with name 'acacia publishings' the constraint is constructed using the == operator provided by the parseswift sdk 8 9 // to be completed below 10 } catch { 11 // hanlde the error (of type parseerror) 12 } 이제 acaciapublishings acaciapublishings , 관련 책을 검색하기 위한 쿼리를 구성할 수 있습니다 우리는 query\<book> query\<book> 클래스를 인스턴스화하여 쿼리를 생성합니다 이 경우, 이 클래스는 query( ) query( ) 라는 정적 메서드를 사용하여 인스턴스화됩니다 book book 객체에서 제공됩니다 이 메서드의 (가변) 인수는 표준 queryconstraint queryconstraint 객체입니다 따라서 우리가 찾고 있는 책은 다음 코드 조각으로 검색됩니다 1 do { 2 let acaciapublishings = try publisher query("name" == "acacia publishings") first() // returns the first publisher with name 'acacia publishings' 3 4 let constraint queryconstraint = try "publisher" == publisher 5 let query = book query(constraint) // creates the query to retrieve all book objects where its publisher field equalt to 'acaciapublishings' 6 7 let books \[book] = try query find() // executes the query synchronously 8 9 // books should contain only one element the book 'a love story' 10 } catch { 11 // hanlde the error (of type parseerror) 12 } 위의 코드 조각에 대한 비동기 구현은 다음과 같이 작성할 수 있습니다 1 // we retrieve the publisher with name 'acacia publishings' 2 publisher query("name" == "acacia publishings") first { result in 3 switch result { 4 case success(let publisher) 5 guard let constraint queryconstraint = try? "publisher" == publisher else { fatalerror() } 6 7 // then, we retrieve the books with the corresponding constraint 8 book query(constraint) find { result in 9 switch result { 10 case success(let books) 11 // books should contain only one element the book 'a love story' 12 break 13 case failure(let error) 14 // handle the error (of type parseerror) 15 break 16 } 17 } 18 19 case failure(let error) 20 // handle the error (of type parseerror) 21 break 22 } 23 } m\ n 관계가 포함된 쿼리 (사례 1) 이 사례를 설명하기 위해, 우리는 다음 시나리오를 고려합니다; 주어진 날짜 이후에 출판된 책을 포함하는 모든 상점을 나열하고자 합니다 (예 01/01/2010 ) 먼저, 책을 선택하기 위한 중간 쿼리가 필요합니다 다음으로, 상점을 나열하기 위한 주요 쿼리를 구성합니다 따라서, 우리는 책을 위한 첫 번째 쿼리를 준비합니다 1 let booksquery = book query("publishingdate" > date(string "01/01/2010")) // we construct the date constraint using the > operator provided by the parseswift sdk 2 3 do { 4 let books = try booksquery find() 5 // to be completed below 6 } catch let error as parseerror { 7 // handle any potential error 8 } catch { 9 // handle any potential error 10 } 그런 다음 우리는 booksquery booksquery 의 결과를 사용하여 상점 쿼리를 구성합니다 메서드 containedin( array ) containedin( array ) 는 이 경우에 필요한 제약 조건을 반환합니다 1 let booksquery = book query("publishingdate" > date(string "01/01/2010")) // we construct the date constraint using the > operator provided by the parseswift sdk 2 3 do { 4 let books = try booksquery find() 5 6 // here is where we construct the stores' query with the corresponding constraint 7 let storesquery = bookstore query(try containedin(key "books", array books)) 8 9 let stores = try storesquery find() 10 11 // stores should containt only one element the 'general books' bookstore 12 } catch let error as parseerror { 13 // handle any potential error 14 } catch { 15 // handle any potential error 16 } 유사하게, 우리는 이 프로세스를 비동기적으로 구현할 수 있습니다 1 let booksquery = book query("publishingdate" > date(string "01/01/2010")) // we construct the date constraint using the > operator provided by the parseswift sdk 2 3 booksquery find { result in 4 switch result { 5 case success(let books) 6 guard let constraint = try? containedin(key "books", array books) else { fatalerror() } 7 let storesquery = bookstore query(constraint) 8 9 storesquery find { result in 10 switch result { 11 case success(let stores) 12 13 case failure(let error) 14 // handle the error (of type parseerror) 15 } 16 } 17 case failure(let error) 18 // handle the error (of type parseerror) 19 } 20 } m\ n 관계가 포함된 쿼리 (사례 2) 주어진 저자, 예를 들어, aaron writer 가 쓴 책이 있는 모든 상점을 선택해야 한다고 가정해 보겠습니다 이를 달성하기 위해 두 개의 추가 쿼리가 필요합니다 저자 aaron writer와 관련된 객체를 얻기 위한 쿼리 ( query\<author> query\<author> )입니다 aaron writer가 쓴 모든 책을 선택하기 위한 쿼리 ( query\<book> query\<book> )입니다 우리가 찾고 있는 상점을 선택하기 위한 주요 쿼리 ( query\<bookstore> query\<bookstore> )입니다 이 쿼리를 구현하는 절차는 이전 것과 매우 유사합니다 1 let authorquery = author query("name" == "aaron writer") // the first query to retrieve the data object associated to 'aaron writer' 2 3 do { 4 let aaronwriter = try authorquery first() 5 6 let booksquery = book query(try containedin(key "authors", array \[aaronwriter])) // the second query to retrieve the books written by 'aaron writer' 7 8 let books = try booksquery find() 9 10 let storesquery = bookstore query(try containedin(key "books", array books)) // the main query to select the stores where the author ('aaron writer') has his books available 11 12 let stores = try storesquery find() 13 14 // stores should contain two items 'books of love' and 'general books' 15 } catch let error as parseerror { 16 // handle the error 17 } catch { 18 // handle the error 19 } 결론 우리는 parseswift sdk parseswift sdk ,를 사용하여 다른 데이터 유형과의 관계에 따라 항목을 선택할 수 있는 관계형 쿼리를 구성할 수 있었습니다