2013-11-02 4 views
7

Nehmen wir ein Kommentare Tabelle hat die folgende Struktur:RethinkDB Index für Filter + orderby

id | author | timestamp | body 

Ich möchte Index verwenden, um effizient die folgende Abfrage ausführen:

r.table('comments').getAll("me", {index: "author"}).orderBy('timestamp').run(conn, callback) 

Gibt es andere effiziente Methode, die ich verwenden kann?

Es sieht so aus, dass der aktuelle Index für ein gefiltertes Ergebnis einer Tabelle nicht unterstützt wird. Wenn Sie einen Index für timestamp Erstellen und Hinzufügen es als Hinweis in orderBy('timestamp', {index: timestamp}) Ich erhalte die folgende Fehlermeldung:

RqlRuntimeError: Indexed order_by can only be performed on a TABLE. in:

Antwort

11

Dies kann mit einer Verbindung Index auf dem „Autor“ erreicht werden und „Zeitstempel“ Feldern aus. Sie können wie so einen solchen Index zu erstellen:

r.table("comments").index_create("author_timestamp", lambda x: [x["author"], x["timestamp"]]) 

Dann können Sie es verwenden, um die Abfrage wie so auszuführen:

r.table("comments") 
.between(["me", r.minval], ["me", r.maxval] 
.order_by(index="author_timestamp) 

Die zwischen Werken wie die get_all in Ihrer ursprünglichen Abfrage tat, weil es nur bekommt Dokumente, die den Autor "mich" und einen beliebigen Zeitstempel haben. Dann machen wir einen order_by auf demselben Index, der nach dem Zeitstempel sortiert (da alle Schlüssel den gleichen Autor haben). Der Schlüssel hier ist, dass Sie nur einen Index pro Tabellenzugriff verwenden können, also müssen wir alle diese Informationen in zu stopfen der gleiche Index.

+0

Dies funktioniert nicht für mich. Und es sieht so aus, als hättest du Python-Syntax hier benutzt ...?! – williamle8300

+0

Das funktioniert und ist super schnell. Vielen Dank :) – codefreak

4

Es ist derzeit nicht möglich, Kette ein getAll mit orderBy Verwendung von Indizes zweimal. Bestellung mit einem Index kann jetzt nur auf einer Tabelle erfolgen.

NB: Der Befehl zum orderBy mit einem Index ist orderBy({index: 'timestamp'}) (keine Notwendigkeit, den Schlüssel zu wiederholen)

2

Die Antwort von Joe Doliner wurde ausgewählt, aber es scheint mir falsch.

Zuerst wurde im Befehl between kein Indexer angegeben. Daher wird between primären Index verwenden.

Zweitens, die between Rückkehr eine Auswahl

table.between(lowerKey, upperKey[, {index: 'id', leftBound: 'closed', rightBound: 'open'}]) → selection 

und orderBy kann nicht auf die Auswahl mit einem Index ausgeführt wird, können nur Tabellenindex verwenden.

table.orderBy([key1...], {index: index_name}) → selection<stream> 
selection.orderBy(key1, [key2...]) → selection<array> 
sequence.orderBy(key1, [key2...]) → array 
1

Sie möchten einen so genannten "zusammengesetzten Index" erstellen. Danach können Sie es effizient abfragen.

 
//create compound index 
r.table('comments') 
.indexCreate(
    'author__timestamp', [r.row("author"), r.row("timestamp")] 
) 

//the query 
r.table('comments') 
.between(
    ['me', r.minval], 
    ['me', r.maxval], 
    {index: 'author__timestamp'} 
) 
.orderBy({index: r.desc('author__timestamp')}) //or "r.asc" 
.skip(0)  //pagi 
.limit(10) //nation! 

Ich verwende gerne zwei Unterstriche für zusammengesetzte Indizes. Es ist nur stilistisch. Es spielt keine Rolle, wie Sie Ihren zusammengesetzten Index benennen.

Referenz: How to use getall with orderby in RethinkDB