聚合框架 - MongoDB:查找具有给定子文档数组的文档



我想查找包含给定子文档的文档,假设我的commits集合中有以下文档:

// Document 1
{ 
  "commit": 1,
  "authors" : [
    {"name" : "Joe", "lastname" : "Doe"},
    {"name" : "Joe", "lastname" : "Doe"}
  ] 
}
// Document 2
{ 
  "commit": 2,
  "authors" : [
    {"name" : "Joe", "lastname" : "Doe"},
    {"name" : "John", "lastname" : "Smith"}
  ] 
}
// Document 3
{ 
  "commit": 3,
  "authors" : [
    {"name" : "Joe", "lastname" : "Doe"}
  ] 
}

想要从上面的集合中得到的只是第一个文档,因为我知道我正在寻找一个有 2 个authors都有相同namelastnamecommit。所以我提出了一个查询: db.commits.find({ $and: [{'authors': {$elemMatch: {'name': 'Joe, 'lastname': 'Doe'}}, {'authors': {$elemMatch: {'name': 'Joe, 'lastname': 'Doe'}}], 'authors': { $size: 2 } })

$size用于筛选出第 3 个文档,但查询仍返回第 2 个文档,因为两者都$elemMatch返回 True。

我不能在子文档上使用索引,因为用于搜索的作者顺序是随机的。有没有办法在不使用 Mongo 的聚合函数的情况下从结果中删除第二个文档?

您在这里要求的内容与标准查询略有不同。实际上,您正在询问"名称"和"姓氏"在数组中的该组合中找到两次或更多次以标识该文档。

标准查询参数与结果中数组元素匹配的"次数"不匹配。但是,当然,您可以使用聚合框架要求服务器为您"计数":

db.collection.aggregate([
    // Match possible documents to reduce the pipeline
    { "$match": {
        "authors": { "$elemMatch": { "name": "Joe", "lastname": "Doe" } }
    }},
    // Unwind the array elements for processing
    { "$unwind": "$authors" },
    // Group back and "count" the matching elements
    { "$group": {
        "_id": "$_id",
        "commit": { "$first": "$commit" },
        "authors": { "$push": "$authors" },
        "count": { "$sum": {
            "$cond": [
                { "$and": [
                    { "$eq": [ "$authors.name", "Joe" ] },
                    { "$eq": [ "$authors.lastname", "Doe" ] }
                ]},
                1,
                0
            ]
        }}
    }},
    // Filter out anything that didn't match at least twice
    { "$match": { "count": { "$gte": 2 } } }
])

所以本质上你但你的条件在$cond运算符内匹配,该运算符返回1匹配的地方和0不匹配的地方,这被传递给$sum以获得文档的总数。

然后过滤掉任何不匹配 2 次或更多次的文档

最新更新