Mongodb 能否在单个聚合管道中按id查找多个文档?
我正在编写一个用户详细信息API视图,并希望添加一个Mongodb 能否在单个聚合管道中按id查找多个文档?,mongodb,mongoose,aggregation-framework,Mongodb,Mongoose,Aggregation Framework,我正在编写一个用户详细信息API视图,并希望添加一个is_following标志,以指示经过身份验证的API用户(用户a)是否在跟踪他们正在查看的用户配置文件(用户B) 在请求时,我只有经过身份验证的API用户的\u id。我可以在一次查询中获取经过身份验证的API用户的following字段,然后继续为他们感兴趣的用户进行第二次查询,但我认为在一次聚合中将该工作传递给数据库(如果可能的话)会更有效 假设我对users集合有以下模式: [ { _id: 1,
is_following
标志,以指示经过身份验证的API用户(用户a)是否在跟踪他们正在查看的用户配置文件(用户B)
在请求时,我只有经过身份验证的API用户的\u id
。我可以在一次查询中获取经过身份验证的API用户的following
字段,然后继续为他们感兴趣的用户进行第二次查询,但我认为在一次聚合中将该工作传递给数据库(如果可能的话)会更有效
假设我对users
集合有以下模式:
[
{
_id: 1,
name: 'David',
following: [2, 3] // David follows Sam and Lucy
},
{
_id: 2,
name: 'Sam',
following: [1] // Sam only follows David
},
{
_id: 3,
name: 'Lucy',
following: [1, 2] // Lucy follows David and Sam
},
]
我想知道是否有可能按照我目前的想法编写聚合:
\u id
后面的数组以某种方式存储在聚合管道中,以便以后针对我们希望查看的用户使用
\u id
再次匹配用户a有兴趣查看的用户(用户B)is\u following
,该字段表示用户B的\u id
是否在我们先前存储的经过身份验证的API用户(用户a)的following
数组中。i、 e登录用户正在跟踪其当前查看的用户配置文件$match
条件的文档的方法
编辑:添加预期输出
如果经过身份验证的用户(用户A)是\u id
2,而被查看的用户用户B是\u id
1:
{
_id: 1,
name: 'David',
following: [2, 3],
is_following: true
}
如果经过身份验证的用户(用户A)是\u id
2,而被查看的用户,用户B是\u id
3:
{
_id: 3,
name: 'Lucy',
following: [1, 2],
is_following: false
}
您的问题不是100%清楚,但您似乎在寻找一个简单的方法,对相同的数据与结果用户进行比较。您可能真的一次只想让单个用户使用它,因此该用户的“选项”通常是这里的“选项” 除了标准结果之外,它没有太多内容,然后使用与“父级”
\u id
进行比较,并将新属性添加到数组中
理想情况下,使用MongoDB 3.6,您可以应用:
对于早期版本,只需在中“显式”命名要返回的字段:
Person.aggregate([
// { "$match": { "_id": 3 } },
{ "$lookup": {
"from": Person.collection.name,
"localField": "following",
"foreignField": "_id",
"as": "following"
}},
{ "$project": {
"_id": 1,
"name": 1,
"following": {
"$map": {
"input": "$following",
"in": {
"_id": "$$this._id",
"name": "$$this.name",
"following": "$$this.following",
"is_following": { "$setIsSubset": [["$_id"], "$$this.following"] }
}
}
}
}}
])
基本原理是,当每个元素都由您检查时,您可以比较它们自己的“followers”
数组和当前用户的\u id
值。或者应用于这种比较。一个将值与一个数组和另一个“两个”数组进行比较
或者,在您甚至没有访问权限的地方,您可以.populate()
,然后以大致相同的方式简单地“重新映射”数组内容:
let people = await Person.find().lean().populate('following');
people = people.map(p => ({
...p,
following: p.following.map(f => ({
...f,
is_following: f.following.some(e => e._id.equals(p._id))
}))
}));
使用该方法进行比较。请注意,由于“对象比较”的工作方式,如果不将ObjectId
值重新映射到字符串,则无法在此处应用
此处的所有表格都会得出相同的结果:
{
"_id" : 1,
"name" : "David",
"following" : [
{
"_id" : 2,
"name" : "Sam",
"following" : [
1
],
"is_following" : true
},
{
"_id" : 3,
"name" : "Lucy",
"following" : [
1,
2
],
"is_following" : true
}
]
}
{
"_id" : 2,
"name" : "Sam",
"following" : [
{
"_id" : 1,
"name" : "David",
"following" : [
2,
3
],
"is_following" : true
}
]
}
{
"_id" : 3,
"name" : "Lucy",
"following" : [
{
"_id" : 1,
"name" : "David",
"following" : [
2,
3
],
"is_following" : true
},
{
"_id" : 2,
"name" : "Sam",
"following" : [
1
],
"is_following" : false
}
]
}
不太清楚你在问什么。也许您应该通过演示来展示基于所提供的数据样本(或当前数据,如果您认为它仍然适用),您期望得到什么样的结果。有些事情看起来是这样的,但是显示您对请求的预期结果会使它更加清晰。另外,请不要使用类似于
ObjectId(“1”)
的东西,这是无效的数据,无法由试图在演示中解决问题的人使用。要么只显示一个真实的ObjectId
值,要么只使用其他有效的值。例如\u id:1
。@NeilLunn关于ObjectId的观点很好。我添加了两个期望输出的示例,希望能让问题更容易理解。因此,我对您的期望输出有点困惑,因为它似乎是相反的。您认为这些结果属于哪个用户(A或B)?只要看最后一个,3跟在1和2后面,因此1是3的跟随者,2不是。你不想让每个潜在的追随者都有is\u following
,看看他们是否在跟踪“家长”用户吗?还是不?这看起来很奇怪,你给出的输出是3,而这个人实际上在后面跟着另一个人。不是“其他人”在跟踪他们,只是给你一个答案。看看它,如果你真的认为这个过程有什么不对的地方,那么告诉我。据我所知,你所问的逻辑模式是,跟随者也在跟随用户,这就是结果所显示的。@NeilLunn感谢你的回答,并为困惑感到抱歉!集合中的每个用户都拥有他们跟踪的用户,而不是跟踪他们的用户。我试图确定被请求的用户以及最终的输出(用户B)是否被认证的API用户(用户A)跟踪。用户B很可能会跟随用户A,但只有当用户A跟随用户B时,is\u following
字段才应设置为true,因为该字段是从经过身份验证的用户的角度来看的。“我在跟踪这个人吗?”,而不是“他们在跟踪我吗?”希望这有助于澄清问题:)
{
"_id" : 1,
"name" : "David",
"following" : [
{
"_id" : 2,
"name" : "Sam",
"following" : [
1
],
"is_following" : true
},
{
"_id" : 3,
"name" : "Lucy",
"following" : [
1,
2
],
"is_following" : true
}
]
}
{
"_id" : 2,
"name" : "Sam",
"following" : [
{
"_id" : 1,
"name" : "David",
"following" : [
2,
3
],
"is_following" : true
}
]
}
{
"_id" : 3,
"name" : "Lucy",
"following" : [
{
"_id" : 1,
"name" : "David",
"following" : [
2,
3
],
"is_following" : true
},
{
"_id" : 2,
"name" : "Sam",
"following" : [
1
],
"is_following" : false
}
]
}