正如这篇文章所建议的,我在这里提出我的问题。
我有一个 MongoDB 集合,其中包含代表两个用户之间友谊的文档
{
"_id": "64a337de4538a04610900f0c",
"user1": "6468022102781d442b82afd7",
"user2": "648c7b6b75231cd99e43d7ab",
"areFriends": true
}
我的目标是编写一个聚合函数,给定两个用户的 ID,返回它们的分离度。说得更清楚一点,就像这样:
- 1 = 直接朋友
- 2 = 朋友的朋友
- 3+ 等等
我遇到了上面的 $graphLookup 示例,现在我想知道如何实现类似的东西。
我的情况与另一篇文章的区别在于,我的文档不是单向关系(从-到),而是双向关系(用户 1,用户 2);因此,无法保证想要的用户存储为用户 1 或用户 2。
在我的代码的其他部分,我通过对输入 ID 进行排序或使用如下条件解决了这个问题:
$cond: {
if: { $eq: ['$user1', userId] },
then: '$user2',
else: '$user1',
},
但是,据我了解, $graphLookup中不支持条件(例如connectFromField)
有谁知道如何面对这个特殊问题吗?我将不胜感激。谢谢。
编辑 这是 Ray 提出的聚合管道的修订版本
{ $match: { user1: id1 } },
{
$graphLookup: {
from: 'spots',
startWith: '$user1',
connectFromField: 'user2',
connectToField: 'user1',
as: 'friendshipsViewLookup',
depthField: 'degree',
maxDepth: 2,
},
},
{
$unwind: {
path: '$friendshipsViewLookup',
preserveNullAndEmptyArrays: true,
},
},
{ $match: { 'friendshipsViewLookup.user2': id2 } },
{
$project: {
user1: 1,
user2: '$friendshipsViewLookup.user2',
degree: {
$add: ['$friendshipsViewLookup.degree', 1],
},
},
},
{
$group: {
_id: { user1: '$user1', user2: '$user2' },
minDegree: { $min: '$degree' },
},
},
{
$project: {
user1: '$_id.user1',
user2: '$_id.user2',
degree: '$minDegree',
},
}
您可以创建一个临时视图以方便您的搜索。创建视图时
friendshipsView
,您可以通过设置过滤器(如)来限制搜索范围(从而提高搜索性能)"areFriends": true
。创建视图的最重要的一点是,我们还对user1
和user2
字段进行了“排序”。我们使用$min
和$max
来确保user1
始终小于user2
。这样,您就可以$graphLookup
正常执行。Mongo Playground 演示如何创建视图
创建视图后,您只需执行
$graphLookup
类似于您提供的 SO 答案的操作。Mongo Playground 演示查询视图
注意:由于我们在创建视图时指定了 2 个输入用户进行搜索,因此如果输入了一对新用户,则需要更新/重新创建视图。您可以考虑使用像这样的聚合管道进行更新,对集合进行一劳永逸的“排序” 。这样,您就不需要每次都创建新视图。
编辑:即使集合已编入索引,也可能对聚合管道没有好处,因为我们正在对视图执行聚合,而视图是临时计算的。您可以考虑使用按需物化视图,它实际上将我们的计算视图存储在数据库中。该步骤与我们创建视图的方式类似。我们只需在聚合管道末尾添加一个
$out
/即可。$merge
friendshipsView
集合。$out
蒙戈游乐场
现在,您的视图已准备好进行查询。
通过修改后的查询,您可以看到它正在
IXSCAN
索引视图中使用。部分
explain
输出:蒙戈游乐场