MongoDB:只返回与某个查询(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版本。感谢您的帮助!

你的尝试看起来很接近,我认为你只需要把它们放在一起。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文档(如果存在)。如果要包含文档的其他字段,则需要显式包含这些字段。请参阅有关投影的文档。

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

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

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

查询执行以下

  1. unwind管道开始,该管道首先提取活动数组中的所有项
  2. match管道查找具有我们要查找的id的数组元素
  3. project管道根据需要返回输出

希望这能帮助

请按如下方式尝试:

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

最新更新