如何让mongo返回一个字段中的数组?

时间:2016-09-16 13:56:18

标签: mongodb mongodb-query

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

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中包含一个或多个指定标记的元素的值。如果可能的话,查询会是什么样的?返回完整元素也很好。我正在使用Mongo 2.6.9。

4 个答案:

答案 0 :(得分:1)

您可以运行以下聚合操作,使用set operators作为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]
                 ]
            }
        }
    }
])

答案 1 :(得分:1)

您可以使用聚合框架。查找查询的替代方法是$elemMatch$projection,这两种方法都只支持返回数组中的第一个匹配元素,因此他们不会为您的案例工作,因为您想要所有的值加上他们赢了&# 39;无论如何都要为你的案子工作(我认为)。您需要按数组值进行过滤,但需要投射其他内容。

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

db.enumerations.aggregate(
 {$match:{"enumeration.name":"enum-1"}},
 {$unwind:"$enumeration.elements"},
 {$unwind:"$enumeration.elements.tags"}, 
 {$match:{"enumeration.elements.tags":{$in:["tag-1","tag-4"]}}}, 
 {$project:{"enumeration.elements.value":1}})

答案 2 :(得分:0)

不确定这是否可行(从内存开始),但似乎需要查看$ elemMatch进行数组查询,然后查看第二个可选参数find,这是用于投影。

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

答案 3 :(得分:0)

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"]
}