选择具有符合某些条件的子数组的文档

时间:2014-08-19 16:59:51

标签: mongodb

我有一个包含以下文档的集合:

{
  _id: "1234",
  _class: "com.acme.classA",
  a_collection: [    
    {
      otherdata: 'somedata',
      type: 'a'
    },
    {
      otherdata: 'bar',
      type: 'a'
    },
    {
      otherdata: 'foo',
      type: 'b'
    }
  ],
  lastChange: ISODate("2014-08-17T22:25:48.918Z")
}

我想通过id和子数组的子集找到所有文档。例如,我想找到ID为“1234”的所有文档,a_collection.type为“a”,给出了这个结果:

{
  _id: "1234",
  _class: "com.acme.classA",
  a_collection: [    
    {
      otherdata: 'somedata',
      type: 'a'
    },
    {
      otherdata: 'bar',
      type: 'a'
    }
  ],
  lastChange: ISODate("2014-08-17T22:25:48.918Z")
}

我试过这个:

db.collection_name.aggregate({
    $match: {
        'a_collection.type': 'a'
    }
},
{
    $unwind: "$a_collection"
},
{
    $match: {
        "a_collection.type": 'a'
    }
},
{
    $group: {
        _id: "$_id",
        a_collection: {
            $addToSet: "$a_collection"
        },

    }
}).pretty()

但这不会返回其他属性(例如'lastChange') 这样做的正确方法是什么?

4 个答案:

答案 0 :(得分:0)

您使用的是PHP吗?

这是你获得“文字”的唯一方法吗?

也许你可以重写它就像一个JSON元素。

类似的东西:

 {
  "_id": "1234",
  "_class": "com.acme.classA",
  "a_collection": [    
    {
      "otherdata": "somedata",
      "type": "a"
    },
    {
      "otherdata": "bar",
      "type": "a"
    },
    {
      "otherdata": "foo",
      "type": "b"
    }
  ]
}

然后你可以使用PHP的json_decode()函数创建一个数组,然后你可以搜索并只返回所需的数据。

编辑:我读了读错。你在寻找像这样的功能吗?

  db.inventory.find(    {
         $or: [ { _id: "1234" }, { 'a_collection.type': 'a' }] 
   } )

[Here] [1]我找到了代码;)[1]:http://docs.mongodb.org/manual/tutorial/query-documents/

答案 1 :(得分:0)

这是正确的查询:

db.collection_name.aggregate({
    $match: {
        'a_collection.type': 'a'
    }
},
{
    $unwind: "$a_collection"
},
{
    $match: {
        "a_collection.type": 'a'
    }
},
{
    $group: {
        _id: "$_id",
        a_collection: {
            $addToSet: "$a_collection"
        },
        lastChange : { $first : "$lastChange" }

    }
}).pretty()

答案 2 :(得分:0)

您想要的查询(以及您的管道)有些奇怪。首先,_id是一个保留字段,上面有唯一索引。使用_id = "1234"查找所有文档的结果只能是0或1个文档。其次,要为数组a_collection.type = "a"的某个元素查找a_collection的文档,您不需要聚合框架。您只需要查找查询:

> db.test.find({ "a_collection.type" : "a" })

因此,这里的所有工作似乎都是将一个文档的子数组缩小到只有a_collection.type = "a"的元素。如果您执行的大部分操作是将它们分开并删除一些以查找结果集,那么为什么在同一文档中包含这些对象?使用a_collection.type = "a"只收集数组元素有多常见,多么真实?也许您希望以不同的方式对数据建模,以便像

这样的查询
> db.test.find({ <some condition>, "a_collection.type" : "a" })

返回正确的文件。我不能说如何使用给定的信息做到最好,但我可以说你当前的方法强烈建议需要修改(如果你包含更多信息或发布一个新问题,我很乐意帮助提出建议)

答案 3 :(得分:0)

我同意你自己提交的答案,但是对于MongoDB 2.6及更高版本中的答案,有一种更好的方法可以使用$map$setDifference。哪个都在该版本中引入。但是在可行的情况下,这种方法要快得多:

db.collection.aggregate([
    { "$match": { "a_collection.type": "a" } },
    { "$project": {
        "$setDifference": [
            { "$map": [
                "input": "$a_collection",
                 "as": "el",
                 "in": {
                     "$cond": [
                         { "$eq": [ "$$el.type", "a" ] },
                         "$$el", 
                         false
                     ]
                 }
            ]},
            [false]
        ]
    }}
])

因此,没有“组”或初始“放松”,这两个都可能是昂贵的选项,以及 $match 阶段。所以MongoDB 2.6做得更好。