2016-01-06 8 views
43

Also, ich habe mit der Umsetzung eine ‚retweet' artige Funktionalität in einer App (iOS, Swift), mit Parse beauftragt worden.parse.com 'retweet' Muster ist zu ausführlich

Dies wurde vor here gefragt, aber das ist a) ziemlich High-Level und b) Ich bekomme die Aufgabe zur Hand - ich brauche nicht unbedingt um Hilfe bei den architektonischen Entscheidungen, wenn es scheint, dass ich offensichtlich vermisse etwas, ich bin glücklich, Feedback zu akzeptieren.

Meine App hat CAUSES, die jeweils von einem USER erstellt werden. Es gibt auch eine FOLLOW-Tabelle mit einem TO- und einem FROM-Benutzer. Zum Anfang frage ich einfach die CAUSES-Tabelle mit der Einschränkung, dass der USER, der gepostet hat, der objectId eines TO-Benutzers (wo der aktuelle Benutzer der FROM-Benutzer ist) in der FOLLOW-Tabelle entspricht. kurz und bündig Mehr:

let getFollowedUsersQuery = PFQuery(className: Constants.kParseClassFollowers) 
getFollowedUsersQuery.whereKey(Constants.kParseFieldFromUser, equalTo: PFUser.currentUser()!) 

let causesQuery = PFQuery(className: Constants.kParseClassCauses) 
causesQuery.whereKey(Constants.kParseFieldFromUser, matchesKey: Constants.kParseFieldToUser, inQuery: getFollowedUsersQuery) 
causesQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in 
    if let causes = objects { 
     for cause in causes { 
      // populate the tableview cells, etc. 
     } 
    } 
}) 

Jetzt habe ich alle Ursachen von den Benutzern, die ich folgen ... das alles ziemlich normal ist.

Hier wird es knifflig.
Jede Ursache hat auch eine Beziehung namens SUPPORTERS. Jetzt muss ich einen Weg entwerfen, um alle CAUSES von Leuten zu bekommen, denen ich nicht folge, aber die in ihrer Liste von Unterstützern einen Benutzer haben, dem ich folge.

ich noch eine elegante Lösung zu finden, obwohl ich eine ‚rohe Gewalt‘ eine nähere mich, und es ist so umständlich und weitschweifig, dass die bessere Hälfte des Gehirns meine Programmierer screaming at me like Susan Powter ist ...

Hier ist ein Beispiel:

let retweetQuery = PFQuery(className: Constants.kParseClassCauses) 
retweetQuery.orderByDescending(Constants.kParseFieldCreatedAt) 
retweetQuery.whereKey(Constants.kParseFieldFromUser, notEqualTo: PFUser.currentUser()!) 
retweetQuery.whereKey(Constants.kParseFieldFromUser, doesNotMatchKey: Constants.kParseFieldToUser, inQuery: getFollowedUsersQuery) 
retweetQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in 
    if let causes = objects { 
     for cause in causes { 
      let supporterRelations = cause.relationForKey(Constants.kParseClassSupporters) 
      let supporterQuery = supporterRelations.query() 
      supporterQuery.findObjectsInBackgroundWithBlock { (supporters, error) in 
       if(error == nil && supporters?.count > 0) { 
        for supporter in supporters! { 
         let user:PFUser = supporter as! PFUser 
         getFollowedUsersQuery.whereKey(Constants.kParseFieldToUser, equalTo: user) 
         getFollowedUsersQuery.whereKey(Constants.kParseFieldFromUser, equalTo: PFUser.currentUser()!) 
         getFollowedUsersQuery.findObjectsInBackgroundWithBlock({ (results, error) -> Void in 
          if(error == nil && results?.count > 0) { 
           for result in results! { 
            // do stuff 
           } 
          } 
         }) 
        } 
       } 
      } 
     } 
    } 
}) 

Nun, dies ist reiner Wahnsinn und unglaublich verschwenderisch (besonders wenn man bedenkt, wie Parst das freie Tier berechnet - ich fühle mich wirklich stark zu meiner API Grenze beitragen könnte, wenn die Produktion geschoben).

Nachdem bereits zwei Anfragen gemacht, ich Redo ein ganz, dann eine weitere Abfrage durchführen für jede Ursache auf die SUPPORTER Beziehungen, dann tun eine andere Abfrage auf jeder Benutzer in dieser Beziehung zu sehen, ob ich ihnen folgen ... und sobald ich diese Informationen habe, muss ich die vom Benutzer unterstützten Ursachen durchlaufen (wegen der asynchronen Rückgabe der Parse-Abfragen glaube ich nicht, dass ich überhaupt zurück in die übergeordneten Schleifen gelangen kann) ... was ich noch nicht implementiert, denn ich bin dabei, das Handtuch zu werfen - muss es einen besseren Weg geben!

Ich hoffe, dass ich hier eine Strategie fehlt bin ...

+4

mir scheint, müssen Sie ein Backlink von Unterstützern zu Ursachen, nein? In diesem Fall würde ich eine Verknüpfungstabelle von BENUTZERN zu CAUSES empfehlen, von denen sie sich in der SUPPORTER-Liste befinden.Dann sind es nur zwei Abfragen - holen Sie alle meine FOLLOWERS, und dann die Ursachen, auf denen jeder USER ein SUPPORTER ist, und dann beseitigen Sie die doppelten Ursachen. – tbondwilkinson

+1

Ja, das macht Sinn ... Ich werde das als eine Option erkunden. –

+2

Ich bin nicht vertraut mit diesem Framework, aber ohne die Semantik zu ändern, können Sie die Syntax ein wenig einfacher machen. Ich schreibe normalerweise 'wenn x = y {für i in x {...' wie 'für i in y ?? [] {... '. Ich würde auch erwägen, 'if error == nil ...' durch 'guard error! = Nil else {return}' zu ersetzen. Diese beiden sparen dir keine Zeilen, aber sie sparen dir Spalten: das würde dein innerstes '// Zeug 'von 9 Ebenen der Einrückung auf 6 reduzieren, was nicht ganz so verrückt ist. –

Antwort

1

@ jesses.co.tt Es tut mir leid, wenn dies zu wenig zu spät ist, auf jeden Fall nehme ich zur Kenntnis, dass ich dies zu beantworten Monate nachdem es gefragt wurde, aber ich denke, das ist es wert, im Allgemeinen zu antworten (und könnte vielleicht immer noch von Wert für dich sein). Im Allgemeinen stimme ich 100% zu, dass die Triple-Abfrage mit Parse a) massiv ineffizient sein wird, so wie es in Rechnung gestellt wird (im alten System) und b) in diesem Sinne, scheint sogar mit der falschen Herangehensweise selbst gehostetes Parse (das kontextuell ist der einzige Mechanismus, der zu diesem Zeitpunkt verwendbar ist, seit Parse jetzt heruntergefahren ist, aber ich denke, wäre immer noch aufgetaucht, wenn Frage gestellt wurde ... egal ...). Es gibt 2 Lösungen, die ich sehe, die das auf eine ziemlich saubere Weise beheben können, vorausgesetzt, dass diese Änderungen an dem allgemeinen Schema/der allgemeinen Architektur vorgenommen werden können.

1) Eine erste Lösung wird der Datensatz neu schematisieren und im wesentlichen „Fremdschlüssel“, um die Untergruppe von Anhängern jeweils User selbst in der User Tabelle hat. Anstatt von Cause ->Supporter ->User zu gehen, könntest du theoretisch Cause ->User machen (wo die Benutzer ihre Unterstützer standardmäßig bekommen, wie es dort eine Spalte wäre). Um dies zu tun in Parse, wenn ich mich richtig erinnere Sie können eine Spalte auf ein Array von einem bestimmten Typ als Wert, und dann object Links dort (die sich schön in der Parse-Dashboard zeigen), die tatsächliche Supporter Tabelle sind Objekte, aber pflegen diese Spalte von Links zu dieser Tabelle in Ihrer User Tabelle.

Während ein bisschen mehr Arbeit auf der Seite write, da Sie manuell (das zu tun haben werden manuell meine ich Schreib der Code selbst, das zu tun, sollte es automatisiert werden, aber es wird nicht kostenlos geschehen in Bezug auf die Entwicklung). Mit dieser etwas mehr im Vorfeld write Betrieb, haben Sie dann einen 2 Schritt read statt 3.

2) Eine zweite Lösung einen anderen Anbieter für diese Art von Daten zu verwenden ist, wenn Abfragegeschwindigkeit ist ein Problem. In mehreren meinen Projekten verwende ich Socket basierten Ansätze für diese Art von Daten-Abfrage-Lookup, und denke wie Pusher oder Firebase (beide sehr verschiedene Ebene der „alle Inklusivität“, Firebase viel mehr wie ein Parse zu sein, aber aus Google diesmal, Pusher ist ein bisschen einfacher und "DIY").

Mit Firebase, zum Beispiel, und eine Steckdose zu diesem Datensatz + ein Schema, in dem die Cause Tabelle selbst einen Cache hat, was User s zu ihnen gehört (und in denen User verfügt über einen Cache ihrer Supporter s), könnte diese 3-Schritt-Suche effektiv 1 Abfrage mit 2 Parametern sein (was ich denke, das ideale Szenario). Ich glaube, dass dies auch mit Parse erreicht werden kann, aber einen weiteren Schritt des Schemafefactorings zur ersten vorgeschlagenen Lösung erfordern würde.

Ich denke, in den Kommentaren wird etwas ähnliches empfohlen (beide obigen Lösungen), aber in einem viel unausgereifteren Format. Ich hoffe, das hilft dem ursprünglichen Fragesteller oder jemandem. Dies könnte auch theoretisch als jemand empfohlen, verwendet PubNub als 1 Kommentar erwähnt, aber es könnte dieses Schema in ein PostgreSQL DB auf AWS gehostet oder Heroku und erreicht exakt die gleichen Mechanismen wie Parse genauso einfach erstellen, ohne der Aufwand.

Auch, weil dies in Referenz, die jetzt nur noch als Open-Source selbst gehosteten Lösung, ein Leitfaden ist hier angeboten wird, parsen, um Hosting-Parse auf eigene Faust auf AWS zu migrieren: link here

+0

Große Antwort, wird bald wieder besuchen! Vielen Dank! –