如何在MongoDB中执行SQL连接等价物?

如何在MongoDB中执行SQL连接等价物?,mongodb,join,Mongodb,Join,如何在MongoDB中执行SQL连接等价物 例如,假设您有两个集合(用户和注释),我希望提取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:9999

如何在MongoDB中执行SQL连接等价物

例如,假设您有两个集合(用户和注释),我希望提取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,获取用户对象,并将它们与注释的结果合并。看来我做错了

你必须按照你描述的方式来做。MongoDB是一个非关系数据库,不支持连接

很多驱动程序都支持一种称为DBRef的规范

DBRef是用于在文档之间创建引用的更正式的规范。DBREF(通常)包括集合名称和对象id。大多数开发人员仅在集合可以从一个文档更改到下一个文档时才使用DBREF。如果引用的集合始终相同,则上面概述的手动引用会更有效

摘自MongoDB文档:数据模型>数据模型参考>

mongodb官方网站上的这一页正好解决了这个问题:

当我们显示故事列表时,我们需要显示发布故事的用户的姓名。如果我们使用关系数据库,我们可以对用户和存储执行连接,并在单个查询中获取所有对象。但MongoDB不支持连接,因此有时需要一些非规范化。这里,这意味着缓存“username”属性

关系纯粹主义者可能已经感到不安,好像我们违反了一些普遍规律。但我们要记住,MongoDB集合并不等同于关系表;每一个都有一个独特的设计目标。规范化表提供了一个原子的、孤立的数据块。然而,文档更接近于作为一个整体来表示对象。在社交新闻网站的案例中,可以认为用户名是发布故事的固有属性

下面是一个“加入”*演员电影收藏的示例:

它使用
.mapReduce()
方法


*join-加入面向文档的数据库的一种替代方法

playORM可以使用S-SQL(可扩展SQL)为您完成这项工作,S-SQL只需添加分区,这样您就可以在分区内进行连接。

您可以使用Postgres在MongoDB上运行SQL查询,包括join。

这取决于您尝试执行的操作

您目前已将其设置为一个规范化数据库,这很好,而且您所采用的方式也很合适

然而,还有其他方法可以做到这一点

您可以有一个posts集合,该集合为每个post嵌入了注释,其中包含对用户的引用,您可以通过迭代查询来获取这些用户。您可以将用户名与注释一起存储,也可以将它们全部存储在一个文档中


NoSQL的特点是它是为灵活的模式和非常快速的读写而设计的。在典型的大数据场中,数据库是最大的瓶颈,与应用程序和前端服务器相比,数据库引擎更少……它们更昂贵但功能更强大,而且硬盘空间相对来说也非常便宜。规范化源于试图节省空间的概念,但它带来的代价是让数据库执行复杂的连接、验证关系的完整性、执行级联操作。如果开发人员正确地设计数据库,所有这些都可以为他们节省一些麻烦

对于NoSQL,如果您接受冗余和存储空间不是问题,因为它们的成本(更新所需的处理器时间和存储额外数据所需的硬盘驱动器成本),那么非规范化就不是问题(对于变成数十万项的嵌入式阵列,这可能是一个性能问题,但大多数情况下这不是一个问题)。此外,每个数据库群集都有多个应用程序和前端服务器。让它们完成繁重的连接,让数据库服务器坚持读写


TL;DR:您所做的很好,还有其他方法。请查看mongodb文档中的数据模型模式,以获得一些很好的示例。

我们可以使用mongodb客户端控制台通过几行简单的函数合并/连接一个集合中的所有数据,现在我们可以执行所需的查询。 下面是一个完整的例子

-作者:

db.authors.insert([
    {
        _id: 'a1',
        name: { first: 'orlando', last: 'becerra' },
        age: 27
    },
    {
        _id: 'a2',
        name: { first: 'mayra', last: 'sanchez' },
        age: 21
    }
]);
-类别:

db.categories.insert([
    {
        _id: 'c1',
        name: 'sci-fi'
    },
    {
        _id: 'c2',
        name: 'romance'
    }
]);
-书籍

db.books.insert([
    {
        _id: 'b1',
        name: 'Groovy Book',
        category: 'c1',
        authors: ['a1']
    },
    {
        _id: 'b2',
        name: 'Java Book',
        category: 'c2',
        authors: ['a1','a2']
    },
]);
-图书借阅

db.lendings.insert([
    {
        _id: 'l1',
        book: 'b1',
        date: new Date('01/01/11'),
        lendingBy: 'jose'
    },
    {
        _id: 'l2',
        book: 'b1',
        date: new Date('02/02/12'),
        lendingBy: 'maria'
    }
]);
-魔法:

db.books.find().forEach(
    function (newBook) {
        newBook.category = db.categories.findOne( { "_id": newBook.category } );
        newBook.lendings = db.lendings.find( { "book": newBook._id  } ).toArray();
        newBook.authors = db.authors.find( { "_id": { $in: newBook.authors }  } ).toArray();
        db.booksReloaded.insert(newBook);
    }
);
-获取新的收集数据:

db.booksReloaded.find().pretty()
-答复:)


我希望这行代码可以帮助您。

我们可以使用mongoDB子查询合并两个集合。举个例子, 评论--

用户--

用于联接的MongoDB子查询--

从新生成的集合中获取结果--

结果--


希望这会有所帮助。

MongoDB不允许加入,但您可以使用插件来处理。检查mongo连接插件。这是最好的,我已经用过了。您可以像下面这样使用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;


            });

    });
var Join=require('mongo-Join').Join,mongodb=require('mongodb'),Db=mongodb.Db,Server=mongodb.Server;
db.open(函数(错误,数据库){
数据库.集合(“指定”,功能(错误,指定){
/*我们可以把条件放在最高层*/
任命。查找({id_医生:id_医生,完整日期:{$gte:start_日期},
完整日期:{$lte:end_dat
`db.commentss.insert([
  { uid:12345, pid:444, comment:"blah" },
  { uid:12345, pid:888, comment:"asdf" },
  { uid:99999, pid:444, comment:"qwer" }])`
db.userss.insert([
  { uid:12345, name:"john" },
  { uid:99999, name:"mia"  }])
`db.commentss.find().forEach(
    function (newComments) {
        newComments.userss = db.userss.find( { "uid": newComments.uid } ).toArray();
        db.newCommentUsers.insert(newComments);
    }
);`
db.newCommentUsers.find().pretty()
`{
    "_id" : ObjectId("5511236e29709afa03f226ef"),
    "uid" : 12345,
    "pid" : 444,
    "comment" : "blah",
    "userss" : [
        {
            "_id" : ObjectId("5511238129709afa03f226f2"),
            "uid" : 12345,
            "name" : "john"
        }
    ]
}
{
    "_id" : ObjectId("5511236e29709afa03f226f0"),
    "uid" : 12345,
    "pid" : 888,
    "comment" : "asdf",
    "userss" : [
        {
            "_id" : ObjectId("5511238129709afa03f226f2"),
            "uid" : 12345,
            "name" : "john"
        }
    ]
}
{
    "_id" : ObjectId("5511236e29709afa03f226f1"),
    "uid" : 99999,
    "pid" : 444,
    "comment" : "qwer",
    "userss" : [
        {
            "_id" : ObjectId("5511238129709afa03f226f3"),
            "uid" : 99999,
            "name" : "mia"
        }
    ]
}`
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;


            });

    });
db.users.find().forEach(
function (object) {
    var commonInBoth=db.comments.findOne({ "uid": object.uid} );
    if (commonInBoth != null) {
        printjson(commonInBoth) ;
        printjson(object) ;
    }else {
        // did not match so we don't care in this case
    }
});
1) Select from the collection you're interested in.
2) From that collection pull out ID's you need
3) Select from other collections
4) Decorate your original results.
 db.actors.insert( { actor: "Richard Gere", movies: ['Pretty Woman', 'Runaway Bride', 'Chicago'] });
 db.actors.insert( { actor: "Julia Roberts", movies: ['Pretty Woman', 'Runaway Bride', 'Erin Brockovich'] });
map = function() {
  for(var i in this.movies){
    key = { movie: this.movies[i] };
    value = { actors: [ this.actor ] };
    emit(key, value);
  }
}

reduce = function(key, values) {
  actor_list = { actors: [] };
  for(var i in values) {
    actor_list.actors = values[i].actors.concat(actor_list.actors);
  }
  return actor_list;
}
{ "_id" : { "movie" : "Chicago" }, "value" : { "actors" : [ "Richard Gere" ] } }
{ "_id" : { "movie" : "Erin Brockovich" }, "value" : { "actors" : [ "Julia Roberts" ] } }
{ "_id" : { "movie" : "Pretty Woman" }, "value" : { "actors" : [ "Richard Gere", "Julia Roberts" ] } }
{ "_id" : { "movie" : "Runaway Bride" }, "value" : { "actors" : [ "Richard Gere", "Julia Roberts" ] } }
{
   $lookup:
     {
       from: <collection to join>,
       localField: <field from the input documents>,
       foreignField: <field from the documents of the "from" collection>,
       as: <output array field>
     }
}
db.comments.aggregate({
    $lookup:{
        from:"users",
        localField:"uid",
        foreignField:"uid",
        as:"users_comments"
    }
})
db.users.aggregate({
    $lookup:{
        from:"comments",
        localField:"uid",
        foreignField:"uid",
        as:"users_comments"
    }
})
 db.getCollection('comments').aggregate([
        {$match : {pid : 444}},
        {$lookup: {from: "users",localField: "uid",foreignField: "uid",as: "userData"}},
   ])
SELECT S.* FROM LeftTable S
LEFT JOIN RightTable R ON S.ID = R.ID AND S.MID = R.MID  
WHERE R.TIM > 0 AND S.MOB IS NOT NULL
db.LeftTable.aggregate([
                        # connect all tables

                        {"$lookup": {
                          "from": "RightTable",
                          "localField": "ID",
                          "foreignField": "ID",
                          "as": "R"
                        }},
                        {"$unwind": "R"}
                   
                        ])
db.LeftTable.aggregate([
                        # connect all tables

                        {"$lookup": {
                          "from": "RightTable",
                          "localField": "ID",
                          "foreignField": "ID",
                          "as": "R"
                        }},
                        {"$unwind": "R"},

                        # define conditionals + variables

                        {"$project": {
                          "midEq": {"$eq": ["$MID", "$R.MID"]},
                          "ID": 1, "MOB": 1, "MID": 1
                        }}
                        ])
db.LeftTable.aggregate([
                        # connect all tables

                        {"$lookup": {
                          "from": "RightTable",
                          "localField": "ID",
                          "foreignField": "ID",
                          "as": "R"
                        }},
                        {"$unwind": "$R"},

                        # define conditionals + variables

                        {"$project": {
                          "midEq": {"$eq": ["$MID", "$R.MID"]},
                          "ID": 1, "MOB": 1, "MID": 1
                        }},

                        # join all conditionals

                        {"$match": {
                          "$and": [
                            {"R.TIM": {"$gt": 0}}, 
                            {"MOB": {"$exists": True}},
                            {"midEq": {"$eq": True}}
                        ]}},

                        # undefine conditionals

                        {"$project": {
                          "midEq": 0
                        }}

                        ])
{
   $lookup:
     {
       from: <collection to join>,
       localField: <field from the input documents>,
       foreignField: <field from the documents of the "from" collection>,
       as: <output array field>
     }
}
SELECT *, <output array field>
FROM collection
WHERE <output array field> IN (SELECT <documents as determined from the pipeline>
                               FROM <collection to join>
                               WHERE <pipeline> );