2012-01-12 13 views
19

Ho una raccolta di utenti, ognuno dei quali può essere abbonato a uno o più servizi. Ogni servizio ha alcuni metadati, incluso il numero di crediti che l'utente ha per quel servizio.jolly di notazione punti Mongodb?

Come posso trovare tutti gli oggetti utente che hanno meno di 50 crediti per qualche servizio se non ho modo di sapere quali saranno le chiavi degli oggetti di servizio?

Concettualmente, sarebbe qualcosa di simile, che non funziona:

db.users.find({services.*.credits : {$lt : 50}}) 

La collezione utenti:

{ 
_id: 4f0ea25072139e4d2000001f, 
services : { 
    a : { credits : 100, score : 2000 }, 
    b : { credits : 200, score : 300 }, 
    c : { credits : 10, score : 1300 } 
    } 
}, 
{ 
_id: 4f0ea25072139e4d2000001f, 
services : { 
    f : { credits : 68, score : 14 }, 
    q : { credits : 1000, score : 102 }, 
    z : { credits : 59, score : 352 } 
    } 
} 

Un altro esempio di quello che voglio fare, nel caso in cui non è chiaro qui, è spiegato qui: http://www.mongodb.org/display/DOCS/Advanced+Queries#comment-346075854

risposta

-1

Penso che sarebbe più facile se metti quell'oggetto di servizi in un array, quindi puoi usare $elemMatch, come:

{ 
    services : [ 
    {key: "a" , credits : 100, score : 2000 }, 
    {key: "b", credits : 200, score : 300 }, 
    {key: "c", credits : 10, score : 1300 } 
    ] 
} 

e

{ 
    _id: 4f0ea25072139e4d2000001f, 
    services : [ 
    {key: "f", credits : 68, score : 14 }, 
    {key: "q", credits : 1000, score : 102 }, 
    {key: "z", credits : 59, score : 352 } 
    ] 
} 

Poi la query si può scrivere sarebbe come questo:

db.coll.find({services: {$elemMatch : {credits: {$lt: 50}}}}); 

risultato:

{ "_id" : ObjectId("4f0f2be07561bf94ea47eec4"), "services" : [ { "key" : "a", "credits" : 100, "score" : 2000 }, { "key" : "b", "credits" : 200, "score" : 300 }, { "key" : "c", "credits" : 10,  "score" : 1300 } ] } 
+0

ho finiscono per cambiare il nostro schema di utilizzare solo un array. Avrei potuto usare $ elemMatch, ma dato che avevo solo bisogno di corrispondere su un singolo criterio, ero in grado di fare: 'db.users.find ({services.credits: {$ lt: 50}})' – stuporglue

+9

-1 perché questa non è una risposta alla domanda. Non tutti sono in grado di modificare lo schema dei dati con cui stanno lavorando. Questa domanda rimane senza risposta. – CommaToast

+0

OK, ho risposto io stesso. Ho trovato un modo per farlo. Pubblicato di seguito. – CommaToast

1

non lo faccio conoscere un modo per farlo usando lo schema che hai e usando. Mi sembra che tu stia abusando di oggetti come array. Se services erano un array (i suggerimenti plurale che dovrebbe essere), si può semplicemente ricerca

db.users.find({"services.credits" : { $lt : 50 }}); 

o utilizzare $elemMatch se è necessario far corrispondere più condizioni su un singolo elemento dell'array.

+0

Quello che volevo veramente era l'array associativo, che mi avrebbe impedito di avere due elementi di array per lo stesso id di servizio. I nostri utenti non dovrebbero mai finire con '{servizi: [{servizio: f, crediti 50}, {servizio: f, crediti: 60}]}'. Un array associativo impone questo, e rende il 90% delle nostre ricerche banali. L'utilizzo di array regolari mi obbliga a cercare l'array prima di eseguire le query per vedere se devo aggiungere alla matrice dei servizi o trovare un elemento e aggiornarlo. – stuporglue

+0

Quasi tutti i controlli di coerenza devono essere eseguiti nel codice. Questo vale anche per gli array associativi.MongoDB non supporta i vincoli nei documenti incorporati: http://waistcode.net/blog/unique-array-keys-in-mongodb, ad esempio un oggetto non può "violare se stesso". – mnemosyn

+0

Questa non è una risposta alla domanda. Il commento di @ stuporglue qui sopra spiega un motivo perfettamente valido e ottimo per aver creato il suo modello di dati nel modo in cui lo ha fatto. È la stessa ragione per cui il nostro modello di dati è stato fatto nel modo in cui lo abbiamo fatto. E ho ancora bisogno di una risposta a questa domanda. Le persone che dicono di non conoscere la risposta, o di accusare la gente di abusare di cose, ecc., Sono solo improduttive. – CommaToast

15

Questa è una risposta effettiva alla tua domanda.

Come è possibile trovare tutti gli oggetti utente che hanno meno di 50 crediti per alcuni servizi se non si ha modo di sapere quali saranno le chiavi degli oggetti di servizio è come segue.

Utilizzare un $ dove query:

db.users.find({ 
    $where: function() { 
     for (var index in this.services) 
      if (this.services[index].credits < 50) 
       return this; 
    } 
}); 
+1

La "query" manca completamente del supporto per gli indici. Non c'è motivo di usare una struttura dati come questa; se non riesci nemmeno a simulare un indice, stai eseguendo una scansione di raccolta ogni volta e potresti anche caricare l'intera raccolta nella RAM e scansionarla lì, che quindi è un esercizio banale in JavaScript. – mnemosyn

+7

Ha chiesto, "Come posso trovare tutti gli oggetti utente che hanno meno di 50 crediti per qualche servizio se non ho modo di sapere quali saranno le chiavi degli oggetti di servizio?" Ho risposto alla sua domanda. Non ho minimizzato i "rispondenti" solo le risposte, perché non erano risposte. Erano persone che dicevano: "Non puoi/non dovresti farlo" quando puoi chiaramente, ed è puramente una questione di opinione se dovresti. Non sono d'accordo sul fatto che "non ci sia alcun motivo per utilizzare la struttura dei dati in questo modo" ... ci sono molte buone ragioni per farlo. Solo perché non li conosci, non è colpa mia né dell'op. – CommaToast

+4

Non guardo il rappresentante della gente, leggo solo la risposta. Non dubito che tu sappia di più su MongoDB di me. Ma se non è una risposta alla domanda che è stata posta allora sono obbligato a svenderlo; Non ho intenzione di non farlo semplicemente perché hai un alto rappresentante. Dire a qualcuno che non c'è modo di fare qualcosa, quando in effetti c'è, non è bello. Dire alle persone che la loro struttura dei dati è inutile solo perché non si vede il punto, non è neanche bello. Forse hanno una grande ragione per usarlo che semplicemente non capisci. Forse se ti chiedessi quale sia il motivo potresti imparare. – CommaToast

Problemi correlati