2013-11-15 7 views
5

Sto usando Rethinkdb 1.10.1 con il driver python ufficiale. Ho una tabella di cose con tag che sono associati ad un utente:Come posso creare un multiindice composto in rethinkdb?

{ 
    "id": "PK", 
    "user_id": "USER_PK", 
    "tags": ["list", "of", "strings"], 
    // Other fields... 
} 

voglio interrogare da user_id e tag (ad esempio, per trovare tutte le cose dall'utente "tawmas" con "tag" tag). A partire da Rethinkdb 1.10 posso creare un multi-indice di come questo:

r.table('things').index_create('tags', multi=True).run(conn) 

La mia domanda sarebbe allora:

res = (r.table('things') 
     .get_all('TAG', index='tags') 
     .filter(r.row['user_id'] == 'USER_PK').run(conn)) 

Tuttavia, questa query ha ancora bisogno per la scansione di tutti i documenti con il tag dato, quindi mi piacerebbe creare un indice composto basato sui campi user_id e tags. Tale indice mi consentirà di interrogare con:

res = r.table('things').get_all(['USER_PK', 'TAG'], index='user_tags').run(conn) 

Non c'è nulla nella documentazione sui multiindici composti. Tuttavia, I ha provato a utilizzare una funzione di indice personalizzata che combina i requisiti per gli indici composti e i multiindice restituendo un elenco di coppie ["USER_PK", "tag"].

Il mio primo tentativo è stato in python:

r.table('things').index_create(
    'user_tags', 
    lambda each: [[each['user_id'], tag] for tag in each['tags']], 
    multi=True).run(conn) 

questo rende lo starter conducente pitone con un MemoryError cercando di analizzare la funzione di indice (immagino list comprehension non sono realmente supportati dal driver).

Così, mi sono girato verso la mia (certamente, arrugginito) javascript e arrivato fino a questo:

r.table('things').index_create(
    'user_tags', 
    r.js(
     """(function (each) { 
      var result = []; 
      var user_id = each["user_id"]; 
      var tags = each["tags"]; 
      for (var i = 0; i < tags.length; i++) { 
       result.push([user_id, tags[i]]); 
      } 
      return result; 
     }) 
     """), 
    multi=True).run(conn) 

Questa viene rifiutata dal server con una curiosa eccezione: rethinkdb.errors.RqlRuntimeError: Could not prove function deterministic. Index functions must be deterministic.

Quindi, qual è la modo corretto per definire un multiindice composto? O è qualcosa di che non è supportato in questo momento?

+0

A proposito. Nell'ultima versione del driver Python Rethink quando viene eseguito, viene visualizzato un messaggio di errore che spiega cosa sto facendo male. È possibile che sia installata una versione precedente del driver? –

+0

Ho la versione 1.10.0-0, che ho installato la scorsa settimana. Non sembra esserci una versione più recente pubblicata su PyPI. Ti riferisci alla versione di sviluppo? – tawmas

risposta

7

Risposta breve:

di lista non funzionano nelle funzioni ReQL. È necessario utilizzare map invece in questo modo:

r.table('things').index_create(
    'user_tags', 
    lambda each: each["tags"].map(lambda tag: [each['user_id'], tag]), 
    multi=True).run(conn) 

Risposta lunga

Questo è in realtà un aspetto un po 'sottile come driver RethinkDB funzionano. Quindi la ragione per cui questo non funziona è che il tuo codice Python non vede effettivamente le copie reali di ogni documento. Così nell'espressione:

lambda each: [[each['user_id'], tag] for tag in each['tags']] 

each non è mai legato a un documento effettivo dal database, è destinato a una variabile pitone speciale che rappresenta il documento.Mi piacerebbe davvero provare a eseguire la seguente solo per dimostrarlo:

q = r.table('things').index_create(
     'user_tags', 
     lambda each: print(each)) #only works in python 3 

E stamperà qualcosa del tipo:

<RqlQuery instance: var_1 > 

il guidatore sa solo che si tratta di una variabile dalla funzione, in particolare, non ha idea se each["tags"] sia un array o cosa (in realtà è solo un altro oggetto astratto molto simile). Quindi python non sa come iterare su quel campo. Fondamentalmente esattamente lo stesso problema esiste in javascript.

+1

Grazie mille! Ho completamente trascurato la funzione della mappa nei documenti. – tawmas