在Mongo集合中,如何查询数组中的特定对象?

时间:2014-08-12 06:50:44

标签: mongodb

我试图从mongodb中的数组中检索一个对象。以下是我的文件:

{
    "_id" : ObjectId("53e9b43968425b29ecc87ffd"),
    "firstname" : "john",
    "lastname" : "smith",
    "trips" : [ 
        {
            "submitted" : 1407824585356,
            "tripCategory" : "staff",
            "tripID" : "1"
        }, 
        {
            "tripID" : "2",
            "tripCategory" : "volunteer"
        }, 
        {
            "tripID" : "3",
            "tripCategory" : "individual"
        }
    ]
}

我的最终目标是仅在trip.submitted缺席时更新,所以我认为我可以查询并确定mongo查找行为的样子 如果我使用$和查询运算符。所以我试试这个:

db.users.find({
    $and: [
      { "trips.tripID": "1" },
      { "trips": { $elemMatch: { submitted: { $exists: true } } } }
    ]
  },
  { "trips.$" : 1 }   //projection limits to the FIRST matching element
)

然后我回来了:

{
    "_id" : ObjectId("53e9b43968425b29ecc87ffd"),
    "trips" : [ 
        {
            "submitted" : 1407824585356,
            "tripCategory" : "staff",
            "tripID" : "1"
        }
    ]
}

大。这就是我要的。 但是,当我运行此查询时

db.users.find({
    $and: [
      { "trips.tripID": "2" },
      { "trips": { $elemMatch: { submitted: { $exists: true } } } }
    ]
  },
  { "trips.$" : 1 }   //projection limits to the FIRST matching element
)

我得到与第一个相同的结果!所以我知道我的查询有些奇怪但不正确。但我不知道是什么。我在查询之间唯一改变的是" trips.tripID" :" 2" ,在我的脑海中,应该提示mongo没有返回任何结果。我的查询出了什么问题?

2 个答案:

答案 0 :(得分:2)

如果您知道数组是按特定顺序排列的,您可以像这样引用数组中的特定索引: -

db.trips.find({"trips.0.submitted" : {$exists:true}})

或者您可以简单地在两个值上进行元素匹配:

db.trips.find({"trips" : {$elemMatch : {"tripID" : "1", 
                                        "submitted" : {$exists:true}
              }}})

相比之下,您的查询正在查找文档,其中两者都是真的,而不是trip行为字段中的两个元素。

答案 1 :(得分:1)

查询的输出是正确的。您的查询要求mongo在其行程数组中返回具有给定 tripId 和字段已提交的文档。您在问题中提供的文档同时满足 tripIds 的两个条件。由于您的投影,您将获得数组 trip 中的第一个元素。

我假设您将按人名过滤记录,然后根据字段存在标准检索行程中的元素。您可以使用以下方法获得您期望的输出:

db.users.aggregate(
    [
        {$match: 
            {
                "firstname" : "john",
                "lastname" : "smith"
            }
        },
        {$unwind: "$trips"},
        {$match:
             { 
                 "trips.tripID": "1" ,
                 "trips.submitted": { $exists: true }
             }
        }
    ]
)

聚合管道的工作原理如下。第一个$match运算符过滤一个文档(在本例中是 john smith的文档)mongodb聚合中的$unwind运算符展开指定的数组(行程在这种情况下),实际上对与父记录相关联的子记录进行非规范化。第二个$match运算符进一步过滤非规范化/展开的文档,以获得根据您的查询所需的文档。