从不同文档中的数组中获取多个对象MongoDb

时间:2015-12-04 05:58:39

标签: arrays performance mongodb

我的收藏品是

/* 1 */
{
    "_id" : ObjectId("566121aa4b88d840eb7d1c50"),
    "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"),
    "array" : [ 
        {
            "id" : 1
        }, 
        {
            "id" : 2
        }, 
        {
            "id" : 3
        }, 
        {
            "id" : 4
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("5661224a4b88d840eb7d1c51"),
    "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"),
    "array" : [ 
        {
            "id" : 1
        }, 
        {
            "id" : 7
        }, 
        {
            "id" : 3
        }, 
        {
            "id" : 5
        }
    ]
}

我需要的是将对象拉入数组'数组'哪里 batchCourseId = ObjectId(" 566122ab94b792fbdf81bcf3")

2<array.id<=5

预期产出

/* 1 */
    {
        "_id" : ObjectId("566121aa4b88d840eb7d1c50"),
        "array" : [             
            {
                "id" : 3
            }, 
            {
                "id" : 4
            }
        ]
    }

/* 2 */
{
    "_id" : ObjectId("5661224a4b88d840eb7d1c51"),
    "array" : [            
        {
            "id" : 3
        }, 
        {
            "id" : 5
        }
    ]
}

已经尝试过了

db.coll.find({"batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3")},
    { array: { $elemMatch: { id: { $gt: 2,$lte: 5} } } })

输出就像

/* 1 */
{
    "_id" : ObjectId("566121aa4b88d840eb7d1c50"),
    "array" : [ 
        {
            "id" : 3
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("5661224a4b88d840eb7d1c51"),
    "array" : [ 
        {
            "id" : 3
        }
    ]
}

关闭但只有数组中的第一个匹配对象在结果

仅供参考,这只是一组数据样本,原始数据更复杂,数量更多

所以请告诉我这样做的最佳做法,表现也很重要

提前致谢

2 个答案:

答案 0 :(得分:2)

您可以使用聚合来实现相同目标。样本如下所示:

db.coll.aggregate(
  {$match: {"batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3")}},
  {$unwind: '$array'},
  {$match: {'array.id': { $gt: 2,$lte: 5}}},
  {$group: {_id: '$_id', array: {$push : '$array'}}}
)

结果:

{ "_id" : ObjectId("5661224a4b88d840eb7d1c51"), "array" : [ { "id" : 3 }, { "id" : 5 } ] }
{ "_id" : ObjectId("566121aa4b88d840eb7d1c50"), "array" : [ { "id" : 3 }, { "id" : 4 } ] }

答案 1 :(得分:2)

在MongoDB中,聚合$unwind会产生 Cartesian_product 问题,因此在大数据集中避免使用$unwind是很好的方法。

如果您在$unwind中使用aggregation,请检查您的示例,然后结果如下所示

db.collectionName.aggregate([
    { "$match": { "batchCourseId": ObjectId("566122ab94b792fbdf81bcf3") }}, 
    { "$unwind": "$array" }
])

以上查询的结果是:

{ "_id" : ObjectId("566121aa4b88d840eb7d1c50"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 1 } }
{ "_id" : ObjectId("566121aa4b88d840eb7d1c50"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 2 } }
{ "_id" : ObjectId("566121aa4b88d840eb7d1c50"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 3 } }
{ "_id" : ObjectId("566121aa4b88d840eb7d1c50"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 4 } }
{ "_id" : ObjectId("5661224a4b88d840eb7d1c51"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 1 } }
{ "_id" : ObjectId("5661224a4b88d840eb7d1c51"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 7 } }
{ "_id" : ObjectId("5661224a4b88d840eb7d1c51"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 3 } }
{ "_id" : ObjectId("5661224a4b88d840eb7d1c51"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 5 } }

这会创建多个文档,并且在集合中的大型文档中会降低性能并延长处理时间。

而不是$unwind使用 $map aggregation-set operator 进行汇总,而查询如下:

db.collection.aggregate([{
  "$match": {
    "batchCourseId": ObjectId("566122ab94b792fbdf81bcf3")
  }
}, {
  "$project": {
    "array": {
      "$setDifference": [{
          "$map": {
            "input": "$array",
            "as": "el",
            "in": {
              "$cond": {
                "if": {
                  "$and": [{
                    "$gt": ["$$el.id", 2]
                  }, {
                    "$lte": ["$$el.id", 5]
                  }]
                },
                "then": "$$el",
                "else": false
              }
            }
          }
        },
        [false]
      ]
    }
  }
}])