两个集合的 ObjectId 的简单 $lookup "left join" 在 Mongo DB 中不起作用
Simple $lookup "left join" of the ObjectId of two collections not working in Mongo DB
我正在使用 Mongo DB Atlas 与 node.js 和双簧管(双簧管将结果流式传输到 html)。我对这一切都是新手,只是学习所有这些技术,所以将理解更简单的解释。
目标是在两个集合之间进行 $lookup,在本例中,是 'review' 到 'place' 的集合。我研究了类似的答案,但要么不起作用,要么使用的是字符串,而不是 ObjectId。
这很简单,只需连接两个集合的 ObjectId,但在使用双簧管时我无法从 'places' 的“左连接”集合中提取数据(参见双簧管代码底部,FWIW)。
这里是两个集合中的文档,然后是代码。我究竟做错了什么?我尝试将它们转换为字符串并加入 .toString() 和 .str,并为 localField 和 foreignField 加上 'place_id.ObjectId' 和 '_id.ObjectId'。还有一件事,我如何才能看到光标中的内容以了解我得到的是什么?调试(cursor.ToArray())没有工作。提前致谢。
review
({
"_id": { "$oid": "5fd27fd9647f7bb815c4c946" },
"place_id": { "$oid": "5fbc37c4fc13ae680b00002b" }, // connect this...
"user_id": { "$oid": "5fbc10ecfc13ae232d000068" },
"title": "Black Forest -- unforgettable!",
"description": "The forest was great.",
"score": { "$numberInt": "5" }
}
place
{
"_id": { "$oid": "5fbc37c4fc13ae680b00002b" }, // connected to _id above
"name": "Black Forest (Schwarzwald)",
"category": "activity",
"city": "Freiburg",
"country": "Germany",
"description": "The Black Forest (German: Schwarzwald [ˈʃvaʁtsvalt] (About this soundlisten)) is a large forested mountain range.]",
"image": { "filename": "1607629020164_black_forest.jpg", "mime": "image/jpeg" },
"state": ""
})
router.get('/', async (req, res, next) => {
debug('get all reviews api');
try {
const q = req.query.q;
const collation = { locale: 'en_US', strength: 1 };
const matchStage = {};
if (q) {
matchStage.$text = { $search: q };
}
const pipeline = [
{
$match: matchStage,
},
{
$lookup: {
from: 'place',
localField: 'place_id',
foreignField: '_id',
as: 'place',
},
},
];
const connection = await db.connect();
const cursor = connection.collection('review').aggregate(pipeline, { collation: collation });
// write the JSON file
res.type('application/json');
res.write('[\n');
for await (const doc of cursor) {
res.write(JSON.stringify(doc));
res.write(',\n');
}
res.end('null]');
} catch (err) {
sendError(err, res);
}
});
光标转到双簧管,变成'item'。当将其放入 html 时,我希望使用 {item.place.name}
之类的模板字符串来获取数据。这就是我访问它的方式,对吗?
const performSearch = () => {
seen = 0;
$('stream-data-spinner').removeClass('d-none');
$('#search-results').html('');
const formData = $('#search-place-form').serialize();
oboe('/api/review?' + formData)
.node('![*]', (item) => {
if (item) {
chunk.push(item);
if (chunk.length >= 1000) {
showChunk(chunk);
}
}
return oboe.drop;
})
.done((_) => {
// show the last chunk
showChunk(chunk);
// hide the spinner
outputSpinner.classList.add('d-none');
})
.fail((res) => {
// show the error
outputSeen.textContent = `ERROR: network error`;
outputSeen.classList.add('text-danger');
outputSpinner.classList.add('text-danger');
});
};
根据您的 MongoDB 聚合查询,您的 place
字段是一个数组。您可能希望 $unwind 将其展平为对象,以便您的双簧管代码访问它。
我正在使用 Mongo DB Atlas 与 node.js 和双簧管(双簧管将结果流式传输到 html)。我对这一切都是新手,只是学习所有这些技术,所以将理解更简单的解释。
目标是在两个集合之间进行 $lookup,在本例中,是 'review' 到 'place' 的集合。我研究了类似的答案,但要么不起作用,要么使用的是字符串,而不是 ObjectId。
这很简单,只需连接两个集合的 ObjectId,但在使用双簧管时我无法从 'places' 的“左连接”集合中提取数据(参见双簧管代码底部,FWIW)。
这里是两个集合中的文档,然后是代码。我究竟做错了什么?我尝试将它们转换为字符串并加入 .toString() 和 .str,并为 localField 和 foreignField 加上 'place_id.ObjectId' 和 '_id.ObjectId'。还有一件事,我如何才能看到光标中的内容以了解我得到的是什么?调试(cursor.ToArray())没有工作。提前致谢。
review
({
"_id": { "$oid": "5fd27fd9647f7bb815c4c946" },
"place_id": { "$oid": "5fbc37c4fc13ae680b00002b" }, // connect this...
"user_id": { "$oid": "5fbc10ecfc13ae232d000068" },
"title": "Black Forest -- unforgettable!",
"description": "The forest was great.",
"score": { "$numberInt": "5" }
}
place
{
"_id": { "$oid": "5fbc37c4fc13ae680b00002b" }, // connected to _id above
"name": "Black Forest (Schwarzwald)",
"category": "activity",
"city": "Freiburg",
"country": "Germany",
"description": "The Black Forest (German: Schwarzwald [ˈʃvaʁtsvalt] (About this soundlisten)) is a large forested mountain range.]",
"image": { "filename": "1607629020164_black_forest.jpg", "mime": "image/jpeg" },
"state": ""
})
router.get('/', async (req, res, next) => {
debug('get all reviews api');
try {
const q = req.query.q;
const collation = { locale: 'en_US', strength: 1 };
const matchStage = {};
if (q) {
matchStage.$text = { $search: q };
}
const pipeline = [
{
$match: matchStage,
},
{
$lookup: {
from: 'place',
localField: 'place_id',
foreignField: '_id',
as: 'place',
},
},
];
const connection = await db.connect();
const cursor = connection.collection('review').aggregate(pipeline, { collation: collation });
// write the JSON file
res.type('application/json');
res.write('[\n');
for await (const doc of cursor) {
res.write(JSON.stringify(doc));
res.write(',\n');
}
res.end('null]');
} catch (err) {
sendError(err, res);
}
});
光标转到双簧管,变成'item'。当将其放入 html 时,我希望使用 {item.place.name}
之类的模板字符串来获取数据。这就是我访问它的方式,对吗?
const performSearch = () => {
seen = 0;
$('stream-data-spinner').removeClass('d-none');
$('#search-results').html('');
const formData = $('#search-place-form').serialize();
oboe('/api/review?' + formData)
.node('![*]', (item) => {
if (item) {
chunk.push(item);
if (chunk.length >= 1000) {
showChunk(chunk);
}
}
return oboe.drop;
})
.done((_) => {
// show the last chunk
showChunk(chunk);
// hide the spinner
outputSpinner.classList.add('d-none');
})
.fail((res) => {
// show the error
outputSeen.textContent = `ERROR: network error`;
outputSeen.classList.add('text-danger');
outputSpinner.classList.add('text-danger');
});
};
根据您的 MongoDB 聚合查询,您的 place
字段是一个数组。您可能希望 $unwind 将其展平为对象,以便您的双簧管代码访问它。