2016-08-09 8 views
1

Ich versuche, die Leistung der Abfrage einer Couchbase-Ansicht zu verbessern, indem Async verwendet wird. Ich habe ihre Dokumentation über die richtige Art und Weise zu lesen, dies zu tun, es geht so etwas wie:Wie bestellt man Ergebnisse von couchbase mit Bulk bekommt

Cluster cluster = CouchbaseCluster.create(); 
Bucket bucket = cluster.openBucket(); 


List<JsonDocument> foundDocs = Observable 
.just("key1", "key2", "key3", "key4", "key5") 
.flatMap(new Func1<String, Observable<JsonDocument>>() { 
    @Override 
    public Observable<JsonDocument> call(String id) { 
     return bucket.async().get(id); 
    } 
}) 
.toList() 
.toBlocking() 
.single(); 

Welche großen und schnell funktioniert, aber da ich auf der Reihenfolge der Ergebnisse verlassen, scheint es, dass ich tun muss etwas zusätzliche Arbeit, um die Ergebnisse geordnet zu halten. Im obigen Beispiel enthält die JsonDocument-Liste alle 5 Dokumente, aber die Reihenfolge ändert sich zufällig von Anruf zu Anruf. Gibt es eine elegante Möglichkeit, das Ergebnis mithilfe von JavaRx-Funktionen oder Couchbase Java SDK-Funktionen zu bestellen?

Die einzige Lösung, die ich mir vorstellen kann, speichert die Ergebnisse in eine HashMap und dann die ursprüngliche Liste von IDs mit dieser HashMap in eine geordnete Liste von JsonDocuments transformieren.

Antwort

2

Statt flatMap, Sie können entweder:

  • concatMap: Auftrag wird, behalten aber eigentlich für jeden inneren GET warten zu vervollständigen vor dem Abfeuern des nächsten (könnte zur sequenziellen Ausführung mit weniger Leistung zurückkehren)
  • concatMapEager: wird sofort interne Observables subscriben (so auslösen innere GET). Behält die Reihenfolge bei, indem Antworten gepuffert werden, die nicht in der richtigen Reihenfolge ankommen, bis sie mit dem richtigen Index in der Sequenz wiedergegeben werden können. Best of zwei Welten in Bezug auf Bestellung und Leistung.
+0

Gibt es einen Grund, concatMap über concatMapEager zu wählen? Die Reihenfolge der inneren GET-Ausführungen spielt keine Rolle, aber die Reihenfolge der zurückgegebenen Liste sollte mit der Eingabeliste übereinstimmen. – Eyal

+0

ConcatMap hat keinen Puffer, der sehr groß werden könnte, wenn zB alle Antworten in umgekehrter Reihenfolge sind und man viel bekommt. Das wäre Speicher Overhead. Ansonsten nicht wirklich AFAIK –

0

würde ich Zip-Operator verwenden, um alle Ihre Observablen verketten, und dann, wenn sie Dokumente Ergebnisse in der Liste hinzufügen, fertig

@Test 
public void zipObservables() { 
    Observable<String> oKey1 = Observable.just("key1").doOnNext(getDocument()); 
    Observable<String> oKey2 = Observable.just("key2").doOnNext(getDocument()); 
    Observable<String> oKey3 = Observable.just("key3").doOnNext(getDocument()); 
    Observable<String> oKey4 = Observable.just("key4").doOnNext(getDocument()); 

    List<Observable<String>> observables = Arrays.asList(oKey1,oKey2,oKey3,oKey4); 
    List<Object> foundDocs = Observable.zip(observables, Arrays::asList) 
      .toBlocking() 
      .single(); 
} 

private Action1<String> getDocument() { 
    return id -> bucket.async().get(id); 
} 

können Sie mehr Zip Beispiele sehen hier https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/combining/ObservableZip.java

+0

Es wäre wahrscheinlich funktionieren, aber die Schlüssel als Eingabeliste gegeben, so dass die Menge des Schlüssels ändern könnte, so dass für mein spezielles Problem wäre es nicht – Eyal

+0

arbeiten können Sie eine Sammlung an Zip Betreiber übergeben, so dass Sie mit gut sein sollten Das. Überprüfen Sie das Update in meinem Beispiel – paul

+0

Immer noch bezieht es sich auf 4 Schlüssel. Kannst du die Methode ändern, um zipObservables (Liste Schlüssel) zu sein und trotzdem die Ergebnisse wie vorgeschlagen zurückgeben? – Eyal