我如何在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,获取用户对象,并将它们与注释的结果合并。看来我做错了。
从Mongo 3.2开始,这个问题的答案大多不再正确。添加到聚合管道中的新的$lookup操作符本质上与左外连接相同:
https://docs.mongodb.org/master/reference/operator/aggregation/lookup/#pipe._S_lookup
从文档中可以看出:
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
当然,MongoDB不是一个关系数据库,开发人员正在谨慎地推荐$lookup的特定用例,但至少在3.2中,使用MongoDB进行连接是可能的。
这取决于你想做什么。
目前您已经将其设置为规范化数据库,这很好,而且您的操作方式也很合适。
然而,还有其他的方法。
您可以有一个帖子集合,其中为每个帖子嵌入了评论,并引用了您可以迭代查询以获得的用户。您可以将用户名与注释一起存储,您可以将它们都存储在一个文档中。
The thing with NoSQL is it's designed for flexible schemas and very fast reading and writing. In a typical Big Data farm the database is the biggest bottleneck, you have fewer database engines than you do application and front end servers...they're more expensive but more powerful, also hard drive space is very cheap comparatively. Normalization comes from the concept of trying to save space, but it comes with a cost at making your databases perform complicated Joins and verifying the integrity of relationships, performing cascading operations. All of which saves the developers some headaches if they designed the database properly.
With NoSQL, if you accept that redundancy and storage space aren't issues because of their cost (both in processor time required to do updates and hard drive costs to store extra data), denormalizing isn't an issue (for embedded arrays that become hundreds of thousands of items it can be a performance issue, but most of the time that's not a problem). Additionally you'll have several application and front end servers for every database cluster. Have them do the heavy lifting of the joins and let the database servers stick to reading and writing.
TL;DR:你现在做的很好,还有其他的方法。查看mongodb文档的数据模型模式以获得一些很棒的示例。http://docs.mongodb.org/manual/data-modeling/
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;
});
});