如何将每个数组字段与MongoDB中的其他字段匹配
Posted
技术标签:
【中文标题】如何将每个数组字段与MongoDB中的其他字段匹配【英文标题】:How to match each array field to other field in Mongodb 【发布时间】:2020-04-18 12:09:32 【问题描述】:我有一个数组如下:
const test = [
"_id": 1,
"name": "apple",
"car": "ford"
,
"_id": 2,
"name": "melon",
"car": "ferrari"
,
"_id": 3,
"name": "perl",
"car": "Renaut"
]
还有Mongodb的文档如下:
[
"name": "perl", "company": "A"
,
"name": "melon", "company": "B"
,
"name": "apple", "company": "C"
,
"name": "apple", "company": "D"
,
"name": "perl", "company": "E"
,
"name": "apple", "company": "F"
]
我想使用 mongodb 聚合得到这个结果:
[
"name": "perl", "company": "A", testInform: "_id": 3, "name": "perl", "car": "Renaut"
,
"name": "melon", "company": "B", testInform: "_id": 2, "name": "melon", "car": "ferrari"
,
"name": "apple", "company": "C", testInform: "_id": 1, "name": "apple", "car": "ford"
,
"name": "apple", "company": "D", testInform: "_id": 1, "name": "apple", "car": "ford"
,
"name": "perl", "company": "E", testInform: "_id": 3, "name": "perl", "car": "Renaut"
,
"name": "apple", "company": "F", testInform: "_id": 1, "name": "apple", "car": "ford"
]
我想将聚合与$match
和$facet
等一起使用,但我不知道具体该怎么做。你能推荐一个解决方案吗?
非常感谢您阅读本文。
【问题讨论】:
【参考方案1】:$lookup 带有管道关键字
db.demo2.aggregate(
$lookup:
from: "demo1",
let: recordName: "$name",
pipeline: [
$match:
$expr:
$and:
[
$eq: [ "$$recordName", "$name" ] ,
]
,
],
as: "testInform"
)
【讨论】:
【参考方案2】:如果 test
数组数据存储在集合中,那么通过 $lookup
聚合实现 O/P 非常简单
$arrayElemAt
为什么?因为查找将在数组中以testInform
的形式获取连接的文档
db.maindocs.aggregate([
$lookup:
from: "testdocs",
localField: "name",
foreignField: "name",
as: "testInform"
,
$project:
_id: 0,
name: 1,
company: 1,
testInform: $arrayElemAt: ["$testInform", 0]
]);
基于 cmets 的更新:
想法是从存储在 mongodb 中的文档中迭代 cursor
Array.prototype.find()
来自 test
的与 name
字段匹配的对象,将其添加到结果中。
const test = [
_id: 1,
name: "apple",
car: "ford"
,
_id: 2,
name: "melon",
car: "ferrari"
,
_id: 3,
name: "perl",
car: "Renaut"
];
const cursor = db.collection("maindocs").find();
const result = [];
while (await cursor.hasNext())
const doc = await cursor.next();
const found = test.find(e => e.name === doc.name);
if (found)
doc["testInform"] = found;
result.push(doc);
console.info("RESULT::", result);
【讨论】:
测试数组未存储在集合中。它只是js中的常量值。您能否为此推荐其他解决方案? @DDDD 已经用另一个解决方案更新了答案。看看它是否适合你。 注意:我在这里使用了async/await
语法,如果这不是您使用的,可以使用callback
样式和forEach
更改迭代。但逻辑保持不变。【参考方案3】:
聚合有一个阶段:遍历test
数组并获取数组元素作为匹配文档和数组中的name
字段的对象(使用$reduce 运算符)。
const test = [ ... , ... ]
db.test_coll.aggregate( [
$addFields:
testInform:
$reduce:
input: test,
initialValue: ,
in:
$cond: [ $eq: [ "$$this.name", "$name" ] ,
$mergeObjects: [ "$$this", "$$value" ] ,
"$$value"
]
] )
【讨论】:
以上是关于如何将每个数组字段与MongoDB中的其他字段匹配的主要内容,如果未能解决你的问题,请参考以下文章