Mongodb 如何让mongo只返回字段中的数组?

Mongodb 如何让mongo只返回字段中的数组?,mongodb,mongodb-query,Mongodb,Mongodb Query,假设以下集合定义,其中示例为此类集合中的一个条目: enumeration : { name: 'enumeration-1' elements: [ { value: 'value-1' tags: ['tag-1', 'tag-2'] }, { value: 'value-2', tags: ['tag-2', 'tag'-3']

假设以下集合定义,其中示例为此类集合中的一个条目:

enumeration : {
    name: 'enumeration-1'
    elements: [
        {
            value: 'value-1'
            tags: ['tag-1', 'tag-2']
        },
        {
            value: 'value-2',
            tags: ['tag-2', 'tag'-3']
        },
        {
            value: 'value-3'
            tags: ['tag-3', 'tag-4']
        }
    ]
}
返回特定枚举非常简单:

db.enumerations.find({ name: 'enumeration-1' })
但是,我需要扩展该查询,以仅返回每个元素在标记列表中至少有一个标记的元素。考虑以下参数:

 1. name: 'enumeration-1'
 2. tags: ['tag-1', 'tag-4']
我需要输出为:

['value-1', 'value-3']

也就是说,我只需要具有枚举1中包含的一个或多个指定标记的元素的值。如果可能的话,查询会是什么样子?返回完整元素也可以。我正在使用Mongo2.6.9

不确定这是否有效(从内存中),但似乎需要查看数组查询的$elemMatch,然后查看要查找的第二个可选参数,即用于投影的参数

db.enumerations.find({ name: 'enumeration-1', elements : {$elemMatch : { $in : ['tag-1', 'tag-4']}}}, {_id:0, 'elements.value':1})

您可以运行以下聚合操作,将其用作hack(脏操作)来生成修剪后的元素数组:

var query = {
    "name": "enumeration-1",
    "tags": ["tag-1", "tag-4"]
};

db.enumerations.aggregate([
    { "$match": { "name": query.name } },
    {
        "$project": {
            "name": 1,
            "elements": {
                "$setDifference": [
                     {
                         "$map": {
                             "input": "$elements",
                             "as": "el",
                             "in": {
                                 "$cond": [
                                     {                                         
                                         "$setEquals": [                                                
                                             { 
                                                 "$setIntersection": [
                                                     "$$el.tags", query.tags
                                                 ] 
                                             },
                                             []
                                         ]                                           
                                    },                                     
                                     false,
                                     "$$el"
                                 ]
                             }
                         }
                     },
                     [false]
                 ]
            }
        }
    }
])

您可以使用聚合框架。find查询中的另一种选择是,或者两者都只支持返回数组中的第一个匹配元素,因此它们不适用于您的案例,因为您需要所有的值,而且它们无论如何也不适用于您的案例(我认为)。您需要按数组值进行筛选,但需要投影其他内容

但这里是它如何在聚合框架中工作的(如果需要,您最终可以做各种事情,例如使结果独特等)

这个函数的输出如下所示

{
  "values" : [ "value-1", "value-3"]
}

我会相应地更正这个问题。然而,我指的是你的第一个例子。我相信这个查询很接近,但没有返回任何结果。我想知道这是否是因为“tags”属性上没有限定符。我修改了查询,使其看起来像是
db.enumerations.find({name:'enumeration-1',elements:{$elemMatch:{tags:{$elemMatch:{$in:{['tags-1','tags-4']}}})
。但是,它返回所有值(包括不期望的值-2)。@predhme是否愿意告诉我您为什么不接受此答案?这将给我建设性的批评,这将使我能够更好地在未来框架我的答案。当我最初接受这个答案时,我在Mongo控制台内测试,这对我来说很好。但是,当我将查询放入Jongo(我们的mongo框架)时,查询没有得到正确解析,这是没有明显原因的。我搜索了他们的文档并尝试了很多方法,但是当从Jongo运行时,查询失败了。我使用的java驱动程序是2.6.9,它与Mongo verison相匹配。我使用的是Jongo 1.2。感谢您的澄清:)我当然更喜欢这个答案,因为结果正好是我想要的(从mongo控制台)。然而,Jongo/mongo java驱动程序似乎不尊重$setDifference。。。我的结果如下:
{“name”:“enumeration-1”,“elements”:{“$setDifference”:{…}
。我在设置的差异处停了下来,因为查询返回表达式似乎不正确……不确定为什么框架没有对其进行计算。似乎使用
$unwind
是您唯一的选择,因为它会为每个数组条目生成每个文档的副本。您必须小心大型数组将使用mor由于笛卡尔积(聚合管道上的内存上限可能为总内存的10%),因此也需要时间来生成和处理。
db.enumerations.aggregate([
  { $match: {"name":"enumeration-1"} },
  { $unwind: "$elements" },
  { $unwind: "$elements.tags" },
  { $match: {"elements.tags": { $in:["tag-1","tag-4"] } }},
  { $group : { _id : null, values: { $push: "$elements.value" } } },
  { $project: {"_id":0, values:1}}
])
{
  "values" : [ "value-1", "value-3"]
}