【问题标题】:Querying array of objects in MongoDB using only find method仅使用 find 方法查询 MongoDB 中的对象数组
【发布时间】:2020-12-13 04:13:55
【问题描述】:

在 MongoDB 3.4 上的 contacts 集合中查看以下文档:

{
    "_id" : ObjectId("58f045526320ef24fc61fdb2"),
    "name" : "John Doe",
    "tags" : [
        {
            "name": "tagA", 
            "created_at": ISODate("2017-01-27T10:30:00Z")
        },
        {
            "name": "tagB", 
            "created_at": ISODate("2017-01-28T13:30:00Z")
        }
    ],
},
{
    "_id" : ObjectId("58f045526320ef24fc61fdb3"),
    "name" : "Johnny Doe",
    "tags" : [
        {
            "name": "tagA", 
            "created_at": ISODate("2016-12-21T19:30:00Z")
        },
        {
            "name": "tagC", 
            "created_at": ISODate("2017-01-28T13:30:00Z")
        }
    ],
}
.
. 
.

是否有任何只使用 find 方法(也不是聚合框架,也不是 $where)可以返回的查询:

  1. 具有以下所有标签的联系人:[tagA, tagC]
  2. 没有所有这些标签的联系人:[tagC, tagD]
  3. 2017年所有标签的联系人

【问题讨论】:

  • 到目前为止您尝试了什么?你得到的错误是什么?
  • 我只是找不到查询来返回满足这些条件的联系人。请注意,它不是返回例如具有 tagA 或 tagC 的联系人的经典查询。
  • 看看stackoverflow.com/questions/23595023/…。它有类似的例子进行“完全匹配”——这意味着这些答案显示了如何找到具有精确标签集的联系人。例如回答问题1,db.collection.find({"tags": {"$not": {"$elemMatch": {"name": {"$nin": ["tagA", "tagC"]}}}}})
  • 谢谢@JeffJ,我想现在我可以使用您在另一篇 stackoverflow 帖子中评论的关键点编写上面的三个查询:将 $not 应用于子集的补集。您现在可以继续回答问题,对每个案例进行查询,以便我可以接受正确的答案。
  • 我真的没有好的数据可以测试。你可以试试db.collection.find({ "tags.name": { $all: [ "tagA" , "tagB" ], $nin: [ "tagC" , "tagD" ]},"tags.created_at":{$gte: ISODate("2017-01-01"),$lt:ISODate("2018-01-01")}});

标签: mongodb mongodb-query


【解决方案1】:

我在Check if every element in array matches condition发现了一个类似的问题。

要查找具有以下所有标签的联系人:[tagA, tagC],您可以使用双重否定来查找没有元素 NOT 在[tagA, tagC] 中的文档

db.collection.find({"tags": {"$not": {"$elemMatch": {"name": {"$nin": ["tagA", "tagC"]}}}}})

要查找没有所有这些标签的联系人:[tagC, tagD]

db.collection.find({"tags": {"$elemMatch": {"name": {"$nin": ["tagC", "tagD"]}}}})

也可以对日期进行类似的查询,尽管使用$or

db.collection.find({"tags": {"$not": {"$elemMatch": {"$or": [ 
    {"createdAt": {"$lt": ISODate("2017-01-01T00:00:00.000Z")}},
    {"createdAt": {"$gt": ISODate("2017-12-31T23:59:59.999Z")}}]}}}})

【讨论】:

  • 我对您的答案投了赞成票,但恕我直言,前两个查询的 @Veeram 解决方案是最好的。请注意,它们更简单,因此更有效。这就是为什么当他正式添加答案时,我会接受他的答案作为正确的答案。但是,感谢关于否定补码的好点,这是第三个查询的正确答案(在我看来)。
猜你喜欢
  • 2020-03-14
  • 1970-01-01
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 2012-05-05
  • 2014-05-13
  • 2021-11-12
相关资源
最近更新 更多