mongoDB: Aggregation - 是不是有相当于原生 node.js 驱动程序的 $lookup 连接?
Posted
技术标签:
【中文标题】mongoDB: Aggregation - 是不是有相当于原生 node.js 驱动程序的 $lookup 连接?【英文标题】: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 很酷,谢谢。只是驱动程序实现和核心之间的一些语法细微差别 - 我认为我的错误可能是由简单的语法调整引起的。
存在“零”语法差异。在所有驱动程序实现中,“管道”始终是对象的“列表/数组”参数。但是,如果您在谈论您无法解决的代码中的“错误”,那么您的问题应该显示“不适合您”的代码,而不是“正在工作”的代码并询问 “我该怎么做做同样的事情吗?”。如果它不起作用,那么显然你没有做同样的事情。
【参考方案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 你是冠军!谢谢一百万!!以上是关于mongoDB: Aggregation - 是不是有相当于原生 node.js 驱动程序的 $lookup 连接?的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB Aggregation - $unwind order 文档是不是与嵌套数组 order 相同
MongoDB 聚合管道(Aggregation Pipeline)