繁体   English   中英

MongoDB:仅返回与某个查询匹配的数组中的文档(JS)

[英]MongoDB: return just the document from an array that matches a certain query (JS)

我有一个 MongoDB 集合,格式如下:

users: {
    {
        user_id: 1000,
        activities: [
           {id: 1, activity: 'swimming'},
           {id: 2, activity: 'running'},
           {id: 3, activity: 'biking'},...
        ]
    },...
}

我想获取与特定 ID 匹配的活动文档。 例如,如果我使用{id: 1}进行查询,我想要{id: 1, activity: 'swimming'}的输出。 目前,我正在尝试使用findOne({activities: {$elemMatch: {id: 1}}}) ,但它返回整个用户文档(用户 ID 和所有活动)。

我正在使用的代码是:

id = req.body.queryID;
db.collection('users').findOne({activities: {$elemMatch: {id}}})
    .then((document) => {
        console.log(document);
        // more code after this
    });

我也尝试使用aggregate()findOne({}, {activities: {$elemMatch: {id}}})进行查询,但我无法弄清楚。

根据db.version()我在 MongoDB 版本 4.4.8 上。 任何帮助表示赞赏!

您可以将aggregate方法与unwindmatchproject管道一起使用

db.users.aggregate([
    {$unwind: "$activities"},
    {$match: {"activities.id": id}},
    {$project: {id: "$activities.id", activity: "$activities.activity", _id: 0}}
])

注意:此代码是使用 mongo shell 语法编写的。

查询执行以下操作

  1. unwind管道开始,它首先拉出活动数组中的所有项目。
  2. match管道找到具有我们正在寻找的 id 的数组元素
  3. project管道根据需要返回输出

希望这可以帮助

请尝试如下:

db.users.aggregate([
      {
        '$unwind': '$activities'
      }, {
        '$match': {
          'id': id
        }
      }, {
        '$project': {
          'activity': '$activities.activity', 
          'id': '$activities.id',
          '_id':0
        }
      }
    ]);

您的尝试看起来很接近,我认为您只需要将它们放在一起即可。 findOne有两个可选参数,一个查询和一个投影。 该查询告诉 MongoDB 查找并返回什么文档。 投影文档告诉 MongoDB 在查询返回的文档中包含哪些字段。

你在这里有什么:

db.collection('users').findOne({ activities: { $elemMatch: { id }}})

传递一个参数,即查询。 它将查找一个文档,其中activities数组中有一个元素的id等于变量id的值。 你也可以这样写:

db.collection('users').findOne({ "activities.id": id })

您还希望仅返回activities数组中具有匹配 ID 的文档。 这是当您执行与其他尝试类似的操作时,其中$elemMatch在第二个参数中,即投影:

db.collection('users').findOne({}, {activities: {$elemMatch: {id}}})

但是因为您传递了一个空查询,MongoDB 将返回任何文档,不一定是包含具有匹配 ID 的活动的文档。

因此,如果您同时通过查询和投影,我认为您应该得到您正在寻找的东西。 它可能看起来像这样:

db.collection('users').findOne({ "activities.id": id }, { activities: { $elemMatch: { id }}})

这将仅包括_id字段和匹配的activities文档(如果存在)。 如果要包含文档的其他字段,则需要显式包含它们。 请参阅有关投影的文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM