我如何在MongoDB中执行SQL Join等效?
例如,假设你有两个集合(用户和评论),我想拉pid=444的所有评论以及每个评论的用户信息。
comments
{ uid:12345, pid:444, comment="blah" }
{ uid:12345, pid:888, comment="asdf" }
{ uid:99999, pid:444, comment="qwer" }
users
{ uid:12345, name:"john" }
{ uid:99999, name:"mia" }
是否有一种方法可以一次性提取具有特定字段的所有评论(例如. ...find({pid:444}))和与每个评论相关的用户信息?
目前,我首先获取符合条件的注释,然后找出结果集中的所有uid,获取用户对象,并将它们与注释的结果合并。看来我做错了。
查找美元(聚合)
对同一数据库中的未分片集合执行左外连接,以从“已连接”集合中筛选文档进行处理。$查找阶段向每个输入文档添加一个新的数组字段,其元素是“已加入”集合中的匹配文档。$查找阶段将这些重新塑造的文档传递给下一个阶段。
$查找阶段的语法如下:
平等的比赛
要在输入文档中的字段与" joined "集合中的文档中的字段之间执行相等匹配,$lookup stage的语法如下:
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
该操作将对应于以下伪sql语句:
SELECT *, <output array field>
FROM collection
WHERE <output array field> IN (SELECT <documents as determined from the pipeline>
FROM <collection to join>
WHERE <pipeline> );
蒙哥URL
您可以使用聚合管道来实现它,但是自己编写它很麻烦。
您可以使用mongo-join-query从您的查询自动创建聚合管道。
这是你的查询的样子:
const mongoose = require("mongoose");
const joinQuery = require("mongo-join-query");
joinQuery(
mongoose.models.Comment,
{
find: { pid:444 },
populate: ["uid"]
},
(err, res) => (err ? console.log("Error:", err) : console.log("Success:", res.results))
);
您的结果将在uid字段中有user对象,您可以链接任意多的层次。您可以填充对用户的引用,从而引用一个Team,再引用其他东西,等等。
免责声明:我编写了mongo-join-query来解决这个问题。
MongoDB不允许连接,但是你可以使用插件来处理。检查mongo-join插件。这是最好的,我已经用过了。你可以直接使用npm安装它,就像这个npm install mongo-join。您可以通过示例查看完整的文档。
(++)非常有用的工具,当我们需要加入(N)个集合
(——)我们可以只在查询的顶层应用条件
例子
var Join = require('mongo-join').Join, mongodb = require('mongodb'), Db = mongodb.Db, Server = mongodb.Server;
db.open(function (err, Database) {
Database.collection('Appoint', function (err, Appoints) {
/* we can put conditions just on the top level */
Appoints.find({_id_Doctor: id_doctor ,full_date :{ $gte: start_date },
full_date :{ $lte: end_date }}, function (err, cursor) {
var join = new Join(Database).on({
field: '_id_Doctor', // <- field in Appoints document
to: '_id', // <- field in User doc. treated as ObjectID automatically.
from: 'User' // <- collection name for User doc
}).on({
field: '_id_Patient', // <- field in Appoints doc
to: '_id', // <- field in User doc. treated as ObjectID automatically.
from: 'User' // <- collection name for User doc
})
join.toArray(cursor, function (err, joinedDocs) {
/* do what ever you want here */
/* you can fetch the table and apply your own conditions */
.....
.....
.....
resp.status(200);
resp.json({
"status": 200,
"message": "success",
"Appoints_Range": joinedDocs,
});
return resp;
});
});