【问题标题】:mongoDB: Aggregation - Is there a equivalent of the $lookup joins for the native node.js driver?mongoDB: Aggregation - 是否有相当于原生 node.js 驱动程序的 $lookup 连接?
【发布时间】:2016-02-05 20:30:35
【问题描述】:

mongodb: 2.1.3

在阅读了一些关于 mongoDB 3.2 的 aggregation enhancements 之后,我对“$look”管道阶段进行左外等连接感到兴奋。

不幸的是,节点驱动程序似乎没有此运算符。(我在native driver docs for node 中没有看到它,当我尝试使用它时出现错误:

更新:这是我尝试过的代码

var cursor = db.collection('messagethreads').aggregate([
        {"$match": {
            _id: new ObjectID(threadID)}
        }, 
        {"$lookup": {
            from: "messages", 
            localField: "_id",
            foreignField: "threadID",
            as: "messagesList"}
        }
    ]);

    cursor.toArray(function(err,messages){
        if(err) {
            res.status(500).json(error);
        }
        else if(convo === null){
            res.status(400).end();
        }
        else{
            res.status(200).json(messages);
        }
    });
});

示例 - 一个 ThreadMessage 文档

{ 
    "_id" : ObjectId("56b4f52c0e6368c00630aee6"), 
    name: "Messages 1"
}

示例 - 消息文档

{
     "_id" : ObjectId("56b4f52c0e6368c00630af08"), 
     "author" : "Nick", 
     "text" : "Hello", 
     "threadID" : ObjectId("56b4f52c0e6368c00630aee6")
},
...

预期结果

{
    "_id" : ObjectId("56b4f52c0e6368c00630aee6"), 
    name: "Messages 1",
    messageList:[
        {
         "_id" : ObjectId("56b4f52c0e6368c00630af08"), 
         "author" : "Nick", 
         "text" : "Hello", 
         "threadID" : ObjectId("56b4f52c0e6368c00630aee6")
        },
        ...
    ]
}

" MongoError: 异常:无法识别的管道阶段名称:'$lookup'"

您可以阅读更多关于连接案例here

问题:是否有预期的方式来执行与 node.js 原生驱动程序等效的操作?

【问题讨论】:

  • 驱动与此无关。聚合管道只是发送到服务器的序列化数据,没有任何解释(除了原生数据格式到 BSON 的转换),所以没有什么可以支持的。只要您的服务器版本支持该操作(MongoDB 3.2 或更高版本),那么您发送到服务器的内容就会被执行。
  • @BlakesSeven 我不明白 - 节点驱动程序的最新版本是 2.1.6 npmjs.com/package/mongodb 。我以为它会具有核心的所有功能,但是当我尝试时失败了并且节点本机驱动程序的文档确实显示 $limit 是聚合游标方法之一。
  • “驱动程序与此无关”的哪一部分如此难以理解? “驱动程序”实现的唯一东西是.aggregate() 方法(实际上是作为执行聚合的数据库命令的包装器)。管道的内容,就像任何查询一样,只是“内容”。 “驱动程序”除了发送它之外没有什么可以做的。驱动程序文档中没有查询或聚合运算符,除非有不支持动态结构分配的语言的“帮助”方法。 JavaScript 可以。
  • @BlakesSeven 很酷,谢谢。只是驱动程序实现和核心之间的一些语法细微差别 - 我认为我的错误可能是由简单的语法调整引起的。
  • 存在“零”语法差异。在所有驱动程序实现中,“管道”始终是对象的“列表/数组”参数。但是,如果您在谈论您无法解决的代码中的“错误”,那么您的问题应该显示“不适合您”的代码,而不是“正在工作”的代码并询问 “我该怎么做做同样的事情吗?”。如果它不起作用,那么显然你没有做同样的事情。

标签: node.js mongodb


【解决方案1】:

“MongoError”异常是驱动程序如何从“服务器”报告任何错误消息,因此这种错误表明连接到的服务器不是支持$lookup的版本,为3.2或更高:

$lookup

3.2 版中的新功能。

对同一数据库中的未分片集合执行左外连接,以过滤来自“已连接”集合的文档以进行处理。 $lookup 阶段在输入文档中的字段与“加入”集合的文档中的字段之间进行相等匹配。

您始终可以通过serverStatus 数据库命令获取您要连接的服务器版本。也在完全可复制的列表中:

var async = require('async'),
    mongodb = require('mongodb'),
    MongoClient = mongodb.MongoClient,
    ObjectId = mongodb.ObjectId;

MongoClient.connect("mongodb://localhost/test",function(err,db) {

  async.series(
    [
      function(callback) {
        db.command({ "serverStatus": 1 }, function(err,status) {
          console.log(status.version);
          callback(err);
        });
      },
      function(callback) {
        async.each(['threadmessage','message'],function(colname,callback) {
          db.collection(colname).remove({},callback);
        },callback);
      },

      function(callback) {
        db.collection('threadmessage').insert(
          {
            "_id" : ObjectId("56b4f52c0e6368c00630aee6"),
            "name": "Messages 1"
          },
          callback
        );
      },

      function(callback) {
        db.collection('message').insert(
          {
            "_id" : ObjectId("56b4f52c0e6368c00630af08"),
            "author" : "Nick",
            "text" : "Hello",
            "threadID" : ObjectId("56b4f52c0e6368c00630aee6")
          },
          callback
        );
      },

      function(callback) {

        var cursor = db.collection('threadmessage').aggregate([
          { "$lookup": {
            "from": "message",
            "localField": "_id",
            "foreignField": "threadID",
            "as": "messagesList"
          }}
        ]);

        cursor.toArray(function(err,result) {
          console.log(JSON.stringify(result,undefined,2));
          callback(err);
        });
      }
    ],
    function(err) {
      if (err) throw err;
      db.close();
    }
  );

});

以及固定驱动程序版本的 package.json,只是为了表明没有驱动程序版本问题:

{
  "name": "lookup",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "async": "^1.5.2",
    "mongodb": "2.1.3"
  }
}

使用受支持的服务器版本提供预期输出:

3.2.0
[
  {
    "_id": "56b4f52c0e6368c00630aee6",
    "name": "Messages 1",
    "messagesList": [
      {
        "_id": "56b4f52c0e6368c00630af08",
        "author": "Nick",
        "text": "Hello",
        "threadID": "56b4f52c0e6368c00630aee6"
      }
    ]
  }
]

因此,如果该列表未在您连接到的数据库上返回 3.2.x,则此处不支持 $lookup 管道操作,您将不得不求助于其他方法,例如拉入“相关”信息“客户端”。

【讨论】:

  • 天哪!刚刚“咔嚓”一声! “服务器”这个词让我很反感,因为我想到了网络服务器。一旦人们安装了 mongoDB,它就像“我的数据库在那里”,我们不认为它是一个服务器。哈哈,我真的必须听起来像一个完整的菜鸟。我检查了一下,即使我有一个 3.2.x 的 GUI,实际服务器是 3.0.8 你是冠军!谢谢一百万!!
猜你喜欢
  • 2013-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 1970-01-01
  • 2015-08-06
  • 2017-02-25
相关资源
最近更新 更多