Mongo查询与投影

3

如何在Mongo中返回匹配条件的列表中所有匹配字典元素。

这是我的数据:

    {"packages": [
       {"package_name" : "abc", "installed_date" : "2016-08-03"},
       {"package_name" : "def", "installed_date" : "2016-08-04"},
       {"package_name" : "ghi", "installed_date" : "2016-08-03"},
       ]
    }

如何查询以获得所有与 {"installed_date" : "2016-08-03"} 匹配的字典?

我尝试过:

db.resource.find({packages: {"$elemMatch": {installed_date: "2016-08-03"}}})

但是这会给我返回数组的所有元素。我想要的是匹配{installed_date: "2016-08-03"}的字典元素。

谢谢!


当您将一个空对象作为第一个参数添加时会发生什么:db.resource.find({}, {packages: {"$elemMatch": {installed_date: "2016-08-03"}}}) - Brian
似乎不起作用,它返回所有其他包,这些包没有那个日期。 - James Sapam
3个回答

6

尝试使用Mongo聚合:

db.resource.aggregate([
  {'$match':{'packages.installed_date':'2016-08-03'}}, 
  {'$unwind':'$packages'}, 
  {'$match':{'packages.installed_date':'2016-08-03'}}, 
  {'$group':{'_id':'$_id', 'packages':{'$push':'$packages'}}}
])

3
如果不想使用$unwind运算符的解决方案,请考虑使用$map$setDifference一起使用,这样您就可以“过滤”数组内容。

这更高效,因为它在单个$project管道中运行,并且$unwind会产生文档的笛卡尔积,即每个数组条目的副本。这将使用更多内存(聚合管道的总内存可能达到10%的内存限制),因此在展开过程中处理文档需要时间:

db.resource.aggregate([
    {
        "$project": {
            "packages": {
                "$setDifference": [
                    {
                        "$map": {
                            "input": "$packages",
                            "as": "item",
                            "in": {
                                "$cond": [
                                    { "$eq": [ "$$item.installed_date", "2016-08-03" ] },
                                    "$$item",
                                    false
                                ]
                            }
                        }
                    },
                    [false]
                ]
            }
        }
    }
])

在上述流水线中,$map操作符实质上创建了一个新的数组字段,该字段保存了一个子表达式对数组的每个元素进行逻辑评估后得出的值。
然后,$setDifference操作符返回一个集合,其中包含出现在第一个集合中但不出现在第二个集合中的元素;即执行相对于第二个集合的相对补集。在本例中,它将返回最终的packages数组,该数组具有installed_date = "2016-08-03"的元素。

1

尝试以下查询:它适用于MongoDB 3.2

db.resource.aggregate([
    {$match:{"packages.installed_date" : "2016-08-03"}},
    { $project: {
        package: {$filter: {
            input: '$packages',
            as: 'package',
            cond: {$eq: ['$$package.installed_date', "2016-08-03"]}
        }}
    }}
])

这将在没有多个匹配条件和$unwind的情况下工作。

谢谢,我会在升级到3.2版本后尝试。 - James Sapam
很好,如果可能的话,请升级到3.2版本。有许多新功能和更好的性能。请参见http://www.slideshare.net/chenghanTsai1/mongodb-300-vs-26x-vs-24x-benchmark。 - Sachin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接