iOS
...
Data Objects
Relationale Datenabfragen mit ParseSwift für iOS
13 min
relationale abfragen einführung in dem vorherigen leitfaden https //www back4app com/docs/ios/parse swift sdk/data objects/query cookbook haben wir detailliert beschrieben, wie wir verschiedene abfragen in einer back4app datenbank durchführen können in diesem leitfaden konzentrieren wir uns auf eine spezifische art von abfrage, die objekte mit beziehungen umfasst voraussetzungen um dieses tutorial abzuschließen, benötigen sie eine app die auf back4app erstellt wurde eine grundlegende ios app, um abfragen zu testen ziel abfragen relationaler daten, die in einer back4app datenbank gespeichert sind, unter verwendung des parseswift sdk parseswift sdk 1 schnelle übersicht über die query\<u>klasse jede abfrage, die auf einer back4app datenbank durchgeführt wird, erfolgt über die generische klasse query\<u> query\<u> der generische parameter u u (entsprechend dem parseobject parseobject protokoll) ist der datentyp der objekte, die wir aus der datenbank abrufen möchten gegeben einen datentyp wie myobject myobject , rufen wir diese objekte aus einer back4app datenbank auf folgende weise ab 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 } sie können mehr über die query\<u> query\<u> klasse hier in der offiziellen dokumentation https //github com/parse community/parse swift 2 speichern sie einige daten in einer back4app datenbank bevor wir mit der ausführung von abfragen beginnen, ist es notwendig, einige daten in einer back4app datenbank einzurichten wir werden fünf arten von objekten speichern 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 } zusätzlich werden wir, um abfragen für relationale daten zu erstellen, die folgenden beziehungen implementieren 1 1 beziehung zwischen buch buch und isbd isbd 1\ n beziehung zwischen buch buch und verlag verlag m\ n beziehung zwischen buch buch und autor autor m\ n beziehung zwischen buchhandlung buchhandlung und buch buch wir fahren nun fort, einige daten in der back4app datenbank zu speichern dieser schritt kann mit swift swift oder direkt über die konsole ihrer app auf der back4app plattform implementiert werden 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 abfragen der daten sobald die datenbank einige beispieldaten hat, beginnen wir mit der ausführung der verschiedenen arten von abfragen, die mit den zuvor beschriebenen beziehungen verbunden sind abfragen mit 1 1 beziehungen gegeben zwei datentypen, die eine 1 1 beziehung teilen ( buch buch und isbd isbd in diesem fall), können wir eines vom anderen wie folgt abrufen die art und weise, wie wir die beziehung in buch buch implementiert haben, ermöglicht es uns, das zugehörige isbd isbd objekt einfach abzurufen, indem wir die include( ) include( ) methode auf der abfrage aufrufen lassen sie uns das isbd isbd vom buch eine liebesgeschichte 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 } andererseits wird eine abfrage, um ein buch buch objekt abzurufen, das mit einem bestimmten isbd isbd verbunden ist, folgendermaßen implementiert wenn wir uns die implementierung von isbd isbd , stellen wir fest, dass die beziehung durch die buch buch eigenschaft (vom typ pointer\<buch> pointer\<buch> ) dargestellt wird dieser zeiger bietet eine reihe von methoden und eigenschaften, um informationen über das objekt abzurufen, auf das er zeigt insbesondere rufen wir die fetch( ) fetch( ) methode auf der buch buch eigenschaft auf, um das zugehörige buch buch 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 } wir sollten bemerken, dass diese implementierung für eine 1 1 beziehung nicht einzigartig ist je nach anwendungsfall können sie 1 1 beziehungen auf unterschiedliche weise implementieren abfragen, die 1\ n beziehungen betreffen in einem szenario, in dem wir alle bücher abfragen müssen, die von einem bestimmten verlag veröffentlicht wurden, müssen wir zuerst den verlag abrufen zum beispiel rufen wir zuerst das datenobjekt ab, das mit dem verlag acacia publishings , verbunden ist je nach situation kann dieser prozess variieren 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 } jetzt, da wir zugriff auf acaciapublishings acaciapublishings , können wir die abfrage konstruieren, um die zugehörigen bücher abzurufen wir fahren fort, die abfrage zu erstellen, indem wir eine query\<book> query\<book> klasse instanziieren in diesem fall wird diese klasse mit der statischen methode query( ) query( ) erstellt, die von dem book book objekt bereitgestellt wird die (variadischen) argumente für diese methode sind die standardmäßigen queryconstraint queryconstraint objekte daher werden die bücher, die wir suchen, mit dem folgenden snippet abgerufen 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 } eine asynchrone implementierung für den obigen codeausschnitt kann folgendermaßen geschrieben werden 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 } abfragen, die m\ n beziehungen betreffen (fall 1) um diesen fall zu veranschaulichen, betrachten wir das folgende szenario; wir möchten alle geschäfte auflisten, die bücher führen, die nach einem bestimmten datum veröffentlicht wurden (z b 01/01/2010 ) zuerst benötigen wir eine zwischenabfrage, um die bücher auszuwählen als nächstes konstruieren wir die hauptabfrage, um die geschäfte aufzulisten daher bereiten wir die erste abfrage für die bücher vor 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 } wir konstruieren dann die abfrage der geschäfte mit den ergebnissen von booksquery booksquery die methode containedin( array ) containedin( array ) gibt die beschränkung zurück, die wir in diesem fall benötigen 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 } ähnlich können wir diesen prozess asynchron implementieren 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 } abfragen, die m\ n beziehungen betreffen (fall 2) angenommen, wir müssen alle geschäfte auswählen, die bücher eines bestimmten autors haben, sagen wir, aaron writer um dies zu erreichen, benötigen wir zwei zusätzliche abfragen eine abfrage ( query\<author> query\<author> ) um das objekt zu erhalten, das mit dem autor aaron writer verbunden ist eine abfrage ( query\<book> query\<book> ) um alle bücher auszuwählen, die von aaron writer geschrieben wurden die hauptabfrage ( query\<bookstore> query\<bookstore> ) um die geschäfte auszuwählen, die wir suchen das verfahren zur implementierung dieser abfragen ist sehr ähnlich zu den vorherigen 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 } fazit mit dem parseswift sdk parseswift sdk , konnten wir relationale abfragen erstellen, die es uns ermöglichten, elemente basierend auf der art der beziehungen auszuwählen, die sie mit anderen datentypen haben