Node.js 如何在';加入';通过$lookup收集?

Node.js 如何在';加入';通过$lookup收集?,node.js,mongodb,mongoose,mongodb-query,aggregation-framework,Node.js,Mongodb,Mongoose,Mongodb Query,Aggregation Framework,我是Mongo的新手,使用v3.2。我有两个集合父集合和子集合。我想使用Parent.aggregate并使用$lookup“加入”子级,然后对子级中的字段执行$text$搜索,并对父级执行日期范围搜索。这是否可能…?根据已经给出的注释,确实不能对搜索结果执行搜索,因为除了第一个管道阶段之外,任何阶段都没有可用的索引。的确,特别是考虑到您确实希望根据“child”集合的结果进行“join”,那么搜索“child”确实会更好 这就得出了一个明显的结论,即为了做到这一点,您需要对“child”集合执

我是Mongo的新手,使用v3.2。我有两个集合父集合和子集合。我想使用Parent.aggregate并使用$lookup“加入”子级,然后对子级中的字段执行$text$搜索,并对父级执行日期范围搜索。这是否可能…?

根据已经给出的注释,确实不能对搜索结果执行搜索,因为除了第一个管道阶段之外,任何阶段都没有可用的索引。的确,特别是考虑到您确实希望根据“child”集合的结果进行“join”,那么搜索“child”确实会更好

这就得出了一个明显的结论,即为了做到这一点,您需要对“child”集合执行聚合,并使用初始查询,然后使用“parent”集合,而不是相反的方式

作为一个工作示例,仅使用核心驱动程序进行演示:

MongoClient.connect('mongodb://localhost/rlookup,函数(err,db){
如果(错误)抛出错误;
var Parent=db.collection('parents');
var Child=db.collection('children');
异步系列(
[
//清理
函数(回调){
async.each([Parent,Child],函数(coll,回调){
coll.deleteMany({},回调);
},回调);
},
//创建索引
函数(回调){
createIndex({“text”:“text”},回调);
},
//创建文档
函数(回调){
异步并行(
[
函数(回调){
Parent.insertMany(
[
{“_id”:1,“name”:“Parent 1”},
{“_id”:2,“name”:“Parent 2”},
{“_id”:3,“name”:“Parent 3”}
],
回拨
);
},
函数(回调){
Child.insertMany(
[
{
“_id”:1,
“家长”:1,
“文本”:“小狗看到这样的乐趣笑了”
},
{
“_id”:2,
“家长”:1,
“文本”:“敏捷的棕色狐狸跳过了懒狗”
},
{
“_id”:3,
“家长”:1,
“文本”:“盘子和勺子一起跑掉了”
},
{
“_id”:4,
“家长”:2,
“文本”:“muffet小姐在这里,塔夫绸”
},
{
“_id”:5,
“家长”:3,
“文本”:“女士是狐狸”
},
{
“_id”:6,
“家长”:3,
“文本”:“每只狗都有它的一天”
}
],
回拨
)
}
],
回拨
);
},
//使用$text和$lookup进行聚合
函数(回调){
儿童聚集(
[
{“$match”:{
“$text”:{“$search”:“狐狸狗”}
}},
{“$project”:{
“家长”:1,
“文本”:1,
“分数”:{“$meta”:“文本分数”}
}},
{“$sort”:{“score”:{“$meta”:“textScore”}},
{“$lookup”:{
“来自”:“父母”,
“localField”:“父项”,
“外域”:“\u id”,
“作为”:“家长”
}},
{“$unwind”:“$parent”},
{“$组”:{
“\u id”:“$parent.\u id”,
“name”:{“$first”:“$parent.name”},
“儿童”:{
“$push”:{
“\u id”:“$\u id”,
“文本”:“$text”,
“分数”:“$score”
}
},
“分数”:{“$sum”:“$score”}
}},
{“$sort”:{“score”:-1}
],
函数(错误、结果){
log(JSON.stringify(result,未定义,2));
回调(err);
}
)
}
],
功能(err){
如果(错误)抛出错误;
db.close();
}
);
});
这将导致在每个
父项中填充的
子项
查询中的匹配项,并按
“分数”
排序:

[
{
“_id”:1,
“名称”:“父项1”,
“儿童”:[
{
“_id”:2,
“文本”:“敏捷的棕色狐狸跳过了懒狗”,
“分数”:1.166667
},
{
“_id”:1,
“文字”:“小狗看到这么有趣,笑了起来”,
“分数”:0.6
}
],
“分数”:1.766666
},
{
“_id”:3,
“名称”:“父级3”,
“儿童”:[
{
“_id”:5,
“文字”:“女士是狐狸”,
“分数”:0.75
},
{
“_id”:6,
“文本”:“每只狗都有它的一天”,
“分数”:0.6666
}
],
“分数”:1.416665
}
]
这最终是有意义的,并且将比从“父项”查询以查找a中的所有“子项”,然后使用
$match
进行“后期筛选”以删除任何不符合条件的“子项”,然后在没有任何匹配项的情况下丢弃“父项”要高效得多

猫鼬风格的“引用”也是如此,在“父”中包含“子”的“数组”,而不是记录在子对象上。因此,只要子级(
\u id
在这种情况下)上的
“localField”
与父级数组中定义的类型相同,即
“foriegnField”
(如果它使用
.populate()
),则仍然可以获得匹配项