我使用MongoDB存储由A腿和B腿组成的呼叫详细记录。
它们之间的关系如下:
cdr
集合中leg_type
等于a
,B腿的字段当然是b
a_leg
,以指示它们属于哪个A腿。此刻,我们检索所需的A形腿,然后遍历它们,对于每个A形腿,我们都检索相关的B形腿(可以是多个),因此全部在客户端。
我想知道是否可以在一个查询中做到这一点,显然您可以使用$lookup (aggregation)。但是,在这种情况下,似乎需要在A形腿上引用一个字段,该字段将是B形腿的数组。
但是我没有那个领域,在我花不必要的时间来建立这样一个领域之前,我想知道我是否可以做不同的事情。
为完整起见,这是我们现在检索CDR的方式:
a_legs = mongo_db['cdr'] \
.find({'group_id': group.id, 'leg_type': 'a'}) \
.sort('times.created', pymongo.DESCENDING) \
.limit(50)
for cdr in a_legs:
# Find B-legs
cdr['b_legs'] = mongo_db['cdr'] \
.find({'a_leg': cdr['call_id'], 'leg_type': 'b'}) \
.sort('times.created', pymongo.ASCENDING)
因此,最重要的问题是:我们可以在对MongoDB的单个查询中完成上述操作吗?
我试图这样做:
db.cdr.aggregate([{
$lookup: {
from: "cdr",
localField: "call_id",
foreignField: "a_leg",
as: "b_legs"
}
}])
但是它没有显示结果。
答案 0 :(得分:0)
我在Studio3T的帮助下找到了答案,它帮助我逐步构建了查询。这就是我最终得到的:
mongo_db['cdr'].aggregate(
[
{
"$match" : {
"group_id" : 585,
"leg_type" : "a"
}
},
{
"$lookup" : {
"from" : "cdr",
"let" : {
"call_id" : "$call_id"
},
"pipeline" : [
{
"$match" : {
"$expr" : {
"$and" : [
{
"$eq" : [
"$leg_type",
"b"
]
},
{
"$eq" : [
"$a_leg",
"$$call_id"
]
}
]
}
}
},
{
"$project" : {
"_id" : False,
"raw" : False,
"leg_type" : False
}
},
{
"$sort" : {
"times.created" : 1
}
}
],
"as" : "b_legs"
}
},
{
"$project" : {
"_id" : False,
"raw" : False,
"leg_type" : False
}
}
],
{
"allowDiskUse" : False
}
);
我需要将$ lookup与pipeline
一起使用。我还必须在call_id
上创建课程索引,以使其快速运行。