2013-07-29 2 views
0

J'ai une collection du type:exacte Réduire la fonction

{ 
    "_id" : ObjectId("51f1fcc08188d3117c6da351"), 
    "cust_id" : "abc123", 
    "ord_date" : ISODate("2012-10-03T18:30:00Z"), 
    "status" : "A", 
    "price" : 25, 
    "items" : [{ 
    "sku" : "ggg", 
    "qty" : 7, 
    "price" : 2.5 
}, { 
    "sku" : "ppp", 
    "qty" : 5, 
    "price" : 2.5 
}] 
} 

Je veux chercher seulement les « objets » dont l'objet « items.qty »> 5 et et « items.sku » == "ggg ".

I appliqué la carte Réduire:

cmd { "mapreduce" : "orders" , "map" : "function map(){var items_out={items:[]};for(i in this.items){items_out.items.push(this.items[i].sku);};emit(this._id,[items_out]);}" , "reduce" : "function reduce(key,values){return {'result':values};}" , "verbose" : true , "out" : { "replace" : "map_reduce"} , "query" : { "$where" : "return this.items.some(function(entry){return entry.qty>5})&&this.items.some(function(entry){return entry.sku=='ggg'})"}}, 

mais je reçois tous les sku valeurs quelque chose comme ceci:

{ "data": [ {  "items": [  "ggg",  "ppp"  ]  } ]} 

considérant qu'il convient de donner que ggg que c'est le seul critère de valeur correspondant.

+2

Pourquoi voudriez-vous faire cela avec M.? Vous pouvez tout aussi bien le faire avec gthe cadre d'agrégation, aussi pourquoi utiliser le '$ where' vous devriez utiliser' $ elemMatch' – Sammaye

Répondre

0

Utilisez la commande suivante:

db.orders.aggregate(
{$unwind : "$items"}, 
{$match : {"items.qty": {$gt: 5 }}}, 
{$match : {"items.sku" : "ggg"}}, 
{$project : {_id:0, items:1}} 
) 
+0

Vous aurez besoin de regrouper les éléments, vous avez également besoin d'un seul match, vous pouvez également faire la correspondance premier à faire usage d'un index – Sammaye

+0

@Sammaye J'ai montré l'exemple d'une collection, mais ce que je fais actuellement est d'appliquer MR à la collecte multiple et de le stocker dans une collection temporaire et que d'interroger la température des données. –

Questions connexes