Mongodb &引用;“地图缩小”;reduce函数查找未定义的值

Mongodb &引用;“地图缩小”;reduce函数查找未定义的值,mongodb,mongo-java,Mongodb,Mongo Java,我有以下收藏: { "_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 }, {

我有以下收藏:

{
  "_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
    }]
}
我的地图功能是:

 var map=function(){emit(this._id,this);}
出于调试目的,我对emit方法进行了如下操作:

var emit = function (key,value){
  print("emit");
  print("key: " + key + "value: " + tojson(value));
  reduceFunc2(key, toJson(value));
}
var reduceFunc2 = function reduce(key,values){
  var val = values;
  print("val",val);
  var items = [];
  val.items.some(function (entry){
    print("entry is:::"+entry);
    if (entry.qty>5 && entry.sku=='ggg'){
      items.push(entry)
    }
  });
  val.items = items;
  return val;
}
和reduce函数,如下所示:

var emit = function (key,value){
  print("emit");
  print("key: " + key + "value: " + tojson(value));
  reduceFunc2(key, toJson(value));
}
var reduceFunc2 = function reduce(key,values){
  var val = values;
  print("val",val);
  var items = [];
  val.items.some(function (entry){
    print("entry is:::"+entry);
    if (entry.qty>5 && entry.sku=='ggg'){
      items.push(entry)
    }
  });
  val.items = items;
  return val;
}
但当我将map应用为:

var myDoc = db.orders.findOne({
  _id: ObjectId("51f1fcc08188d3117c6da351")
});
map.apply(myDoc);
我得到以下错误:

emit key: 51f1fcc08188d3117c6da351 value:
{
  "_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
    }
  ]
}

value:: undefined
Tue Jul 30 12:49:22.920 JavaScript execution failed: TypeError: Cannot call method 'some' of undefined

您可以发现,它们是打印值中的一个项目字段,属于数组类型,即使在未定义的情况下,它也会抛出错误。如果有人知道我的错误在哪里。

您的
reduceFunc2
函数中有错误:

var reduceFunc2 = function reduce(key,values){
  var val = values[0]; //values is an array!!!
  // ...
}
Reduce函数用于将使用相同的
键发出的元素数组缩减为单个文档。因此,它接受一个数组。每个键只发射一次,因此它是一个带有单个元素的数组

现在,您将能够:

重写
emit
函数的方式已损坏,因此不应使用它

更新。如果只有一个文档与给定的键关联,Mongo可能会跳过reduce操作,因为减少单个文档没有意义

MapReduce
的思想是将每个文档映射到一个键值对数组中,以便在下一步进行缩减。如果有多个值与给定的键关联,
Mongo
运行
reduce
操作以将其缩减为单个文档。Mongo期望
reduce
函数以与发出的元素相同的格式返回缩减后的文档。这就是为什么Mongo可以为每个键运行
减少
操作的任意次数(最多为
发出的次数)。如果没有要减少的内容(例如,如果只有一个元素),也不能保证将调用
reduce
操作

因此,最好将
map
逻辑移动到适当的位置

更新2。无论如何,您为什么要在这里使用
MapReduce
?您只需查询所需的文档:

db.orders.find({}, {
  items: {
    $elemMatch: {
      qty: {$gt: 5},
      sku: 'qqq'
    }
  }
})
更新3。如果您确实想使用
MapReduce
执行此操作,请尝试以下操作:

db.runCommand({
  mapreduce: 'orders',
  query: {
    items: {
      $elemMatch: {
        qty: {$gt: 5},
        sku: 'ggg'
      }
    }
  },
  map: function map (){
    this.items = this.items.filter(function (entry) {
      return (entry.qty>5 && entry.sku=='ggg')
    });
    emit(this._id,this);
  },
  reduce: function reduce (key, values) {
    return values[0];
  },
  verbose: true,
  out: {
    merge: 'map_reduce'
  }
})

我得到以下结果:{u id:ObjectId(“51f1fcc0888d317c6da351”),“value:{u id:ObjectId(“51f1fcc0888d317c6da351”),“cust id:“abc123”,“ord_date”:ISODate(“2012-10-03T18:30:00Z”),“status:“A”,“price”:25,“items:[{sku:“ggg”,“qty”:7,“价格”:2.5},{“sku”:“ppp”,“数量”:5,“价格”:2.5}]}}我得到了以下结果,而根据reduce逻辑,项应该只有一个对象。它清楚地表明它没有使用reduce:,“timeMillis”:1,“counts”:{“input”:3,“emit”:3,“reduce”:0,“output”:3},“ok”:1,}我将使用MR,因为我必须查询多个集合,然后将结果合并并返回给用户。您所做的不是
MapReduce
。您只是在文档上调用自己的
map
函数。@Leonid Beschastny我知道,但即使在执行map reduce时,我也没有得到结果,所以我试图通过从map调用reduce来调试它。