Arrays MongoDB-对数组参数元素执行操作的查询

Arrays MongoDB-对数组参数元素执行操作的查询,arrays,mongodb,mapreduce,Arrays,Mongodb,Mapreduce,我是MongoDB的新手,我正在试着弄清楚我是否可以使用MongoDB方便地执行这个查询,并具有良好的性能。我希望将数字和数组参数传递给查询,并使用它们对集合中每个文档中的数组值执行逐元素操作。这可能吗 e、 g.集合包含以下文档: { "name" : "item1", "m" : 5.2, "v" : 1.1, "data1" : [ 0, 0, 0.3, 0.7, 0.95, 0.9, 0.75, 0.4, 0.1, 0 ], "data2" : [

我是MongoDB的新手,我正在试着弄清楚我是否可以使用MongoDB方便地执行这个查询,并具有良好的性能。我希望将数字和数组参数传递给查询,并使用它们对集合中每个文档中的数组值执行逐元素操作。这可能吗

e、 g.集合包含以下文档:

{
    "name" : "item1",
    "m" : 5.2,
    "v" : 1.1,
    "data1" : [ 0, 0, 0.3, 0.7, 0.95, 0.9, 0.75, 0.4, 0.1, 0 ],
    "data2" : [ 0, -1, 0, 1, 1, 0 ]
}
我还有另一个“搜索”文档,可能看起来像这样:

{
    "x" : 8,
    "K" : 1,
    "dataA" : [ 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 0.5],
    "dataB" : [ 0, -2, 0, 1, 1, 0 ]
}
我想使用上述搜索文档对上面返回包含以下内容的集合运行查询或map reduce:

{
    "name",
    "y" = fn(m, v, x, K) = Kvx^(1/m) (not the real formula but just an example)
    "dataF" = Max(i=0..9) {data1[i] * dataA[i] }
    "dataS" = Sum(j=0..5) {data2[j] * dataB[j] }
}
where y>0
因此,对于上面的示例,返回的结果是

{
    "name" : "item1",
    "y" : 1 * 1.1 * 8^5.2 = 1.641
    "dataF" : Max(..., 0.4*0.5, 0.1*1, 0 * 0.5 ) = 0.2
    "dataS" : 0*0 + (-1)*(-2) + 0*0 + 1*1 + 1*1 + 0*0 = 4
}
使用MongoDB是否可能/方便


注意:在我的应用程序中,将使用标准MongoDB操作在搜索中包含更多标准条件,因此我希望在查询中包含上述处理,并避免在客户端执行此操作。

以下是map/reduce版本:

db.data.save({
  "name" : "item1",
  "m" : 5.2,
  "v" : 1.1,
  "data1" : [ 0, 0, 0.3, 0.7, 0.95, 0.9, 0.75, 0.4, 0.1, 0 ],
  "data2" : [ 0, -1, 0, 1, 1, 0 ]
});

db.data.mapReduce( function() {
  var searchdoc = {
    "x" : 8,
    "K" : 1,
    "dataA" : [ 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 0.5],
    "dataB" : [ 0, -2, 0, 1, 1, 0 ]
  };

  var result = {name: this.name};
  result.y = searchdoc.K * this.v * Math.pow(searchdoc.x, 1 / this.m);
  if(result.y > 0) {
    result.dataF = 0;
    for(i=0;i<this.data1.length;i++) {
      var f = this.data1[i] * searchdoc.dataA[i];
      if(f > result.dataF) {
        result.dataF = f;
      }
    } 
    result.dataS = 0;
    for(i=0;i<this.data2.length;i++) {
      var s = this.data2[i] * searchdoc.dataB[i];
      result.dataS += s;
    } 
    emit(this.name, result);
  }
}, function(key, values){}, {out: {inline: 1}});
这是shell版本:

db.data.save({
  "name" : "item1",
  "m" : 5.2,
  "v" : 1.1,
  "data1" : [ 0, 0, 0.3, 0.7, 0.95, 0.9, 0.75, 0.4, 0.1, 0 ],
  "data2" : [ 0, -1, 0, 1, 1, 0 ]
});

var searchdoc = {
  "x" : 8,
  "K" : 1,
  "dataA" : [ 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 0.5],
  "dataB" : [ 0, -2, 0, 1, 1, 0 ]
};

var search = function(searchdoc) {
  db.data.find().forEach(function(obj) {
    var result = {name:obj.name};
    result.y = searchdoc.K * obj.v * Math.pow(searchdoc.x, 1 / obj.m);
    if( result.y > 0 ) {
      result.dataF = 0;
      for(i=0;i<obj.data1.length;i++) {
        var f = obj.data1[i] * searchdoc.dataA[i];
        if(f > result.dataF) {
          result.dataF = f;
        }
      } 
      result.dataS = 0;
      for(i=0;i<obj.data2.length;i++) {
        var s = obj.data2[i] * searchdoc.dataB[i];
        result.dataS += s;
      } 
      db.results.save(result); 
    }
  });
}

search(searchdoc);

db.results.find();
{ "_id" : ObjectId("4f08ffe4264d23670eeaaadf"), "name" : "item1", "y" : 1.640830939540542, "dataF" : 0.2, "dataS" : 4 }
db.data.save({
“名称”:“项目1”,
“m”:5.2,
“v”:1.1,
“数据1”:[0,0,0.3,0.7,0.95,0.9,0.75,0.4,0.1,0],
“数据2”:[0,-1,0,1,1,0]
});
var searchdoc={
“x”:8,
“K”:1,
“数据A”:[0,0,0,0,0,0,0,0,0,0.5,1,0.5],
“数据”:[0,-2,0,1,1,0]
};
var search=函数(searchdoc){
db.data.find().forEach(函数(obj){
var result={name:obj.name};
result.y=searchdoc.K*obj.v*Math.pow(searchdoc.x,1/obj.m);
如果(结果y>0){
result.dataF=0;
对于(i=0;i result.dataF){
result.dataF=f;
}
} 
result.dataS=0;

对于(i=0;iThanks@wes)快速响应,非常有趣,您提出的解决方案非常有用,我将加载一些数据并尝试这两种方法,尝试获得比较性能的感觉,并将发布一些结果。干杯
db.data.save({
  "name" : "item1",
  "m" : 5.2,
  "v" : 1.1,
  "data1" : [ 0, 0, 0.3, 0.7, 0.95, 0.9, 0.75, 0.4, 0.1, 0 ],
  "data2" : [ 0, -1, 0, 1, 1, 0 ]
});

var searchdoc = {
  "x" : 8,
  "K" : 1,
  "dataA" : [ 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 0.5],
  "dataB" : [ 0, -2, 0, 1, 1, 0 ]
};

var search = function(searchdoc) {
  db.data.find().forEach(function(obj) {
    var result = {name:obj.name};
    result.y = searchdoc.K * obj.v * Math.pow(searchdoc.x, 1 / obj.m);
    if( result.y > 0 ) {
      result.dataF = 0;
      for(i=0;i<obj.data1.length;i++) {
        var f = obj.data1[i] * searchdoc.dataA[i];
        if(f > result.dataF) {
          result.dataF = f;
        }
      } 
      result.dataS = 0;
      for(i=0;i<obj.data2.length;i++) {
        var s = obj.data2[i] * searchdoc.dataB[i];
        result.dataS += s;
      } 
      db.results.save(result); 
    }
  });
}

search(searchdoc);

db.results.find();
{ "_id" : ObjectId("4f08ffe4264d23670eeaaadf"), "name" : "item1", "y" : 1.640830939540542, "dataF" : 0.2, "dataS" : 4 }