2015-10-13 18 views

risposta

5

A partire da MongoDB versione 3.4 possiamo e l'operatore $indexOfArray restituisce l'indice in cui è possibile trovare un determinato elemento nell'array.

$indexOfArray accetta tre argomenti. Il primo è il nome del campo dell'array con prefisso $.

Il secondo è l'elemento e il terzo facoltativo è l'indice per avviare la ricerca in. $indexOfArray restituisce il primo indice in cui viene trovato l'elemento se l'indice per avviare la ricerca non è specificato.


Demo:

> db.collection.insertOne({ "_id" : 123, "food": [ "apple", "mango", "banana", "mango" ] }) 
{ "acknowledged" : true, "insertedId" : 123 } 
> db.collection.aggregate([ { "$project": { "matchedIndex": { "$indexOfArray": [ "$food", "mango" ] } } } ]) 
{ "_id" : 123, "matchedIndex" : 1 } 
> db.collection.aggregate([ { "$project": { "matchedIndex": { "$indexOfArray": [ "$food", "mango", 2 ] } } } ]) 
{ "_id" : 123, "matchedIndex" : 3 } 
> db.collection.aggregate([ { "$project": { "matchedIndex": { "$indexOfArray": [ "$food", "apricot" ] } } } ] ) 
{ "_id" : 123, "matchedIndex" : -1 } 
+0

Questa risposta è la migliore per la versione 3.4+, ma se si utilizza la versione precedente, dovrebbe seguire la risposta di @BlakesSeven –

4

Non c'è davvero nessun altro modo ("lato server") che usare mapReduce:

db.collection.mapReduce(
    function() { 
     emit(this._id, this.food.indexOf("mango")); 
    }, 
    function() {}, // reducer never gets called since all _id is unique 
    { 
     "out": { "inline": 1 }, 
     "query": { "food": "mango" } 
    } 
) 

E 'l'unica cosa che restituirà qualcosa d'altro in una forma modificata diverso dal documento stesso , oltre all'utilizzo della valutazione JavaScript necessaria per determinare la risposta,

Purtroppo non esiste un operatore "nativo" che lo faccia.

A meno che non sia necessario per scopi di aggregazione reali, è meglio fare semplicemente una "corrispondenza indice di array" nel codice nativo nel client quando si tratta di una base "per documento".

+0

lavorato come un fascino! Ma che dire delle prestazioni sulla grande collezione quando invochi mapReduce? –

+0

@JamesYang Penso che sia necessario cogliere il punto che non penso che dovresti farlo comunque, a meno che tu non abbia effettivamente bisogno di aggregare ulteriormente il risultato (come già detto). Non esiste un'alternativa lato server (anch'essa già dichiarata), quindi si è bloccati con mapReduce nel caso "lato server" o si elabora l'indice dell'array per documento nel client (come già raccomandato). –

+0

Con le opzioni '{jsMode: true}', è buono per le prestazioni? nella tua esperienza –

0

In mongo shell (in Robomongo anche) vorrei fare le seguenti operazioni:

var food = db.getCollection('yourCollection').findOne({_id: '123'}).food; 
    print('Index of mango: ' + food.indexOf('mango')); 

oppure è possibile salvare questo codice in any_file.js e quindi eseguire da linea di comando:

mongo your_db any_file.js 

Produrrà qualcosa del genere:

MongoDB shell version: 2.4.9 
    connecting to: localhost:27017/your_db 
    Index of mango: 2 
+0

una soluzione, ma forse non pratico –

Problemi correlati