2009-07-24 22 views
5

sto usando quello che sembra essere un trucco comune per la creazione di una vista join:Qual è il valore massimo per una chiave CouchDB composta?

// a Customer has many Orders; show them together in one view: 
function(doc) { 
    if (doc.Type == "customer") { 
    emit([doc._id, 0], doc); 
    } else if (doc.Type == "order") { 
    emit([doc.customer_id, 1], doc); 
    } 
} 

So che posso utilizzare la seguente query per ottenere un unico customer e tutti i relativi Order s:

?startkey=["some_customer_id"]&endkey=["some_customer_id", 2] 

Ma ora ho legato la mia domanda molto strettamente al mio codice di vista. C'è un valore che posso mettere dove ho messo il mio "2" per dire più chiaramente, "Voglio tutto legato a questo cliente"? Penso che ho visto

?startkey=["some_customer_id"]&endkey=["some_customer_id", {}] 

Ma io non sono sicuro che sia {}certo per ordinare dopo tutto il resto.

Credito a cmlenz per il metodo di join.

ulteriori chiarimenti alla CouchDB wiki page on collation:

La query startkey=["foo"]&endkey=["foo",{}] corrisponderà maggior chiavi dell'array con "foo" nel primo elemento, come ["foo","bar"] e ["foo",["bar","baz"]]. Tuttavia esso non corrisponde ["foo",{"an":"object"}]

Così {} è ritardo nell'ordinamento, ma sicuramente non ultima .

risposta

1

Invece di cercare di trovare il maggior possibile valore per la seconda elemento la propria chiave di array, vorrei suggerire invece cercando di trovare il almeno possibile valore maggiore rispetto alla prima : ?startkey=["some_customer_id"]&endkey=["some_customer_id\u0000"]&inclusive_end=false.

+0

Nota le guardie "inclusive_end" contro il caso ridicolo in cui hai effettivamente una chiave del modulo "some_customer_id \ u0000", non includendo i documenti che corrispondono al "tasto finale" nel risultato. – user359996

0

CouchDB è scritto principalmente in Erlang. Non penso che ci sarebbe un limite superiore per una dimensione di stringhe composte/tuple di chiavi composite diverse dalle risorse di sistema (ad esempio una chiave così lunga che ha usato tutta la memoria disponibile). I limiti della scalabilità di CouchDB sono sconosciuti secondo il sito CouchDB. Immagino che potresti continuare ad aggiungere campi in un'enorme chiave primaria composita e l'unica cosa che ti impedirebbe di trovare risorse di sistema o limiti rigidi come le dimensioni massime integer nell'architettura di destinazione.

Poiché CouchDB memorizza tutto utilizzando JSON, è probabilmente limitato ai valori numerici più grandi dallo standard ECMAScript. Tutti i numeri in JavaScript sono memorizzati come IEEE 754 a virgola mobile in virgola mobile. Credo che il doppio a 64 bit possa rappresentare valori compresi tra - 5e-324 e +17979931348623157e + 308.

+0

Forse non ero abbastanza chiaro. L'ID per quel cliente non cambia tra i valori minimo e massimo. CouchDB, tuttavia, consente le chiavi composte. Ordina prima dalla prima voce (costante qui, uguale a "some_customer_id"), quindi dal secondo (null per la chiave di avvio, 2 o {} per il tasto di fine) e così via. Mi chiedo se (e perché) {} sia il valore massimo possibile per una chiave nell'ordinazione di CouchDB. –

+0

Penso che il problema sia nel titolo della mia domanda - Rinominerò per chiarezza. –

+0

Oh, non ho visto che stavi parlando di tasti compositi. Sembra che ci siano dei piccoli limiti su CouchDB. Dubito che ci sia un limite rigido alla dimensione della tupla per la chiave composita. Credo che le risorse di sistema verrebbero testate per alcune operazioni db se si crea una tabella con migliaia di campi e centinaia di campi come parte dell'indice composito. –

0

Sembra che sarebbe bello avere una funzione in cui endKey potrebbe essere inclusivo anziché esclusivo.

+0

In realtà, "endkey" è incluso di default. Devi specificare "endkey_inclusive = false" per ottenere un comportamento esclusivo. – user359996

0

Questo dovrebbe fare il trucco:

?startkey=["some_customer_id"]&endkey=["some_customer_id", "\uFFFF"] 

Ciò dovrebbe includere tutto ciò che inizia con un carattere meno di \ uFFFF (tutti i caratteri Unicode)

+2

Io non la penso così. L'articolo che hai collegato dice che tutte le stringhe vengono prima di tutti gli array, che a loro volta vengono prima di tutti gli Hash. Quindi ["some_customer_id", "\ uFFFF"] è "minore di" ["some_customer_id", {}]. –

+0

che ne dici:?key = ["some_customer_id"] & include_docs = true – bogphanny

+0

Questa non è una query di database relazionale. La virgola non è una congiunzione implicita. Tutti i tasti emessi per questa vista sono array a due elementi, quindi la tua query non darebbe risultati. – user359996

2

ho due pensieri.

Usa timestamp

Invece di usare semplici 0 e 1 per il loro comportamento fascicolazione, utilizzare un timestamp che il record è stato creato (ammesso che sono parte integrante della documentazione) alla [doc._id, doc.created_at]. Quindi puoi interrogare la tua vista con una startkey di data sufficientemente anticipata (probabilmente l'epoca probabilmente funzionerà), e una endkey di "now", ad esempio date +%s. Quel range chiave dovrebbe sempre includere tutto, e ha il vantaggio aggiuntivo di raccogliere per data, che è probabilmente quello che vuoi comunque.

o, solo che non ti preoccupare

si può solo indice dal customer_id e nulla più. Questo avrebbe il vantaggio di poter interrogare usando solo key=<customer_id>. Certo, i record non verranno raccolti quando torneranno, ma è un problema per la tua applicazione? A meno che non ti aspetti un sacco di record, probabilmente sarebbe banale semplicemente estrarre il record del cliente dall'elenco una volta che hai recuperato i dati dalla tua applicazione.

Per esempio in Ruby:

customer_records = records.delete_if { |record| record.type == "customer" }

In ogni modo, i timestamp è probabilmente la risposta più attraente per il vostro caso.

Problemi correlati