【问题标题】:Retrieve mongodb documents by some conditions通过某些条件检索 mongodb 文档
【发布时间】:2021-02-20 21:10:11
【问题描述】:

我尝试使用满足某些条件的 Node.JS 从 MongoDB 集合中检索数据。我有一个名为 Events 的集合,其中包含字段 number_of_persons、category 和 users_attended。事件文档示例:

{ 
    "category":"123",
    "number_of_persons":3,
    "users_attended":["345","456","567","786"]
}

Users_attended 是对 UserAttended 集合的引用,其中包含字段 id、user、accepted 和 cancelled。 示例:

{
   "id":"345",
   "user":"1",
   "accepted":true,
   "canceled":false
}

查询有一个类别数组,如 ['123','1234','12345'],我应该返回在这个数组中具有类别 id 的所有事件。此外,类别向量可以是空数组,在这种情况下,我应该返回所有事件而不按类别过滤。查询的另一个条件是 user_attended 参考是否有许多条目的 accepted=truecanceled=false 少于 event(3) 的人数。我应该通过聚合来做到这一点,我尝试对类别使用 $in 运算符,对 user_attended 使用 $map 但没有结果。有人可以帮我吗?

谢谢

【问题讨论】:

  • 您好,这个语句:"查询的另一个条件是,如果 user_attended 引用的条目数量已经接受=true 和 cancelled=false 小于事件的人数(3 )"不清楚你能详细说明吗?
  • @DheemanthBhat 是的,当然。用户可以加入活动。当他加入一个事件时,他将被插入到 UserAttended 集合中(id:1,用户:345,接受:false,取消:false),并且他的 ref 将被插入到事件集合中的 user_attended 字段中(例如,对于事件文档:{ id:"1", category:"123", user_attended:["1"], number_of_persons: 5. 每个参加活动的用户都可以被接受(接受将设置为true)或拒绝(接受将保持为false) .
  • @DheemanthBhat 当我搜索一个事件时,我应该只返回具有可用插槽的事件(将接受字段设置为 true 的 user_attended 的数量低于事件的 number_of_persons 个)。

标签: node.js mongodb mongoose mongodb-query


【解决方案1】:

在您的管理器文件(包含查询的 node.js 文件)中设置此条件以在 categories 为空时跳过检查。

let condition = {};
if(Array.isArray(categories) && categories.length > 0) {
  condition = {
    "category": {
      $in: categories // Can have values like ["1234", "123"]
    }
  }
}

eventsModel.aggregate([
  { $match: condition },
  // Rest of the query as shown below

试试这个查询:

db.events.aggregate([
    {
        $match: {
            "category": {
                $in: ["1234", "123"]
            }
        }
    },
    {
        $lookup: {
            from: "UserAttended",
            let: { users_attended: "$users_attended" },
            pipeline: [
                {
                    $match: {
                        "accepted": true,
                        "canceled": false,
                        $expr: { $in: ["$_id", "$$users_attended"] }
                    }
                }
            ],
            as: "users_attended"
        }
    },
    {
        $match: {
            $expr: {
                $gt: ["$number_of_persons", { $size: "$users_attended" }]
            }
        }
    }
]);

输出:

{
    "_id" : ObjectId("60310979127fac3244c8f0d9"),
    "category" : "123",
    "number_of_persons" : 3,
    "users_attended" : [
        {
            "_id" : ObjectId("603108bf127fac3244c8f0d3"),
            "user" : "1",
            "accepted" : true,
            "canceled" : false
        },
        {
            "_id" : ObjectId("603108bf127fac3244c8f0d4"),
            "user" : "2",
            "accepted" : true,
            "canceled" : false
        }
    ]
}

这就是我的events 收藏的样子:

/* 1 createdAt:2/20/2021, 6:37:05 PM*/
{
    "_id" : ObjectId("60310979127fac3244c8f0d9"),
    "category" : "123",
    "number_of_persons" : 3,
    "users_attended" : [
        ObjectId("603108bf127fac3244c8f0d3"),
        ObjectId("603108bf127fac3244c8f0d4"),
        ObjectId("603108bf127fac3244c8f0d5")
    ]
},

/* 2 createdAt:2/20/2021, 6:37:05 PM*/
{
    "_id" : ObjectId("60310979127fac3244c8f0da"),
    "category" : "1234",
    "number_of_persons" : 3,
    "users_attended" : [
        ObjectId("603108bf127fac3244c8f0d6"),
        ObjectId("603108bf127fac3244c8f0d7"),
        ObjectId("603108bf127fac3244c8f0d8")
    ]
}

这就是我的UserAttended 收藏的样子:

/* 1 createdAt:2/20/2021, 6:33:59 PM*/
{
    "_id" : ObjectId("603108bf127fac3244c8f0d3"),
    "user" : "1",
    "accepted" : true,
    "canceled" : false
},

/* 2 createdAt:2/20/2021, 6:33:59 PM*/
{
    "_id" : ObjectId("603108bf127fac3244c8f0d4"),
    "user" : "2",
    "accepted" : true,
    "canceled" : false
},

/* 3 createdAt:2/20/2021, 6:33:59 PM*/
{
    "_id" : ObjectId("603108bf127fac3244c8f0d5"),
    "user" : "3",
    "accepted" : false,
    "canceled" : false
},

/* 4 createdAt:2/20/2021, 6:33:59 PM*/
{
    "_id" : ObjectId("603108bf127fac3244c8f0d6"),
    "user" : "4",
    "accepted" : true,
    "canceled" : false
},

/* 5 createdAt:2/20/2021, 6:33:59 PM*/
{
    "_id" : ObjectId("603108bf127fac3244c8f0d7"),
    "user" : "5",
    "accepted" : true,
    "canceled" : false
},

/* 6 createdAt:2/20/2021, 6:33:59 PM*/
{
    "_id" : ObjectId("603108bf127fac3244c8f0d8"),
    "user" : "6",
    "accepted" : true,
    "canceled" : false
}

【讨论】:

  • 非常感谢您的回答 Dheemanth,我认为它是正确的,但我有一个问题。在 UserAttended 集合中,我没有“id”字段,我只有“_id”,它是一个 ObjectID,并且这个引用被插入到 user_attended 数组中。我如何通过_id匹配?我尝试在匹配表达式中将“$id”替换为“$_id”,但没有结果...
  • $_id 替换$id 对我有用。检查更新的答案。发布您的 eventsUserAttended 架构,您可能会在那里遗漏一些东西。
  • 如果可能的话,还要在您编写此查询的地方发布代码。检查拼写错误。
猜你喜欢
  • 2014-02-20
  • 2020-11-27
  • 2020-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
相关资源
最近更新 更多