我正在寻找有关联接的一些信息以及它们在MongoDB
中的行为方式。虽然我很欣赏NoSQL数据库背后的大量功能是将所有信息存储在文档中,并且该文档包含尽可能多的信息,这样您就不必进行多次查询
但是,我也很欣赏在某些情况下您可能希望尽量减少数据重复,以便最大限度地降低一致性问题的风险。
使用文档引用时,有没有办法返回单个文档?我已经尝试了$lookup
函数,虽然它确实返回了正确的结果,但它为每个数组条目返回一个文档。
假设以下结构:
客户:
{
_id: ObjectId("578d706916f07969c4b0cad1"),
name: "fred",
orders: [ObjectId("578d706916f07969c4b0cad2"),ObjectId("578d706916f07969c4b0cad3")]
}
订单:
{
_id: ObjectId("578d706916f07969c4b0cad2"),
date: xxxx,
items: [a,b,c,d]
},
{
_id: ObjectId("578d706916f07969c4b0cad2"),
date: xxxx,
items: [x,y,z]
}
使用查找,我可以获得2个文档的结果,每个订单附加一个客户数据,但是我正在寻找带有数组或订单信息的单个文档 - embedded document
。即以下结构
{
_id: ObjectId("578d706916f07969c4b0cad1"),
name: "fred",
orders: [
{
_id: ObjectId("578d706916f07969c4b0cad2"),
date: xxxx,
items: [a,b,c,d]
},
{
_id: ObjectId("578d706916f07969c4b0cad2"),
date: xxxx,
items: [x,y,z]
}]
}
这可能在MongoDB
内吗?或者join
进程是否与SQL数据库紧密匹配,在尝试加入数据时,您将始终返回重复的客户信息?我知道数据可以转换为应用程序中的单个文档,例如node
但是,从编写查询的方式来看,是否可以返回预先格式化的文档?
答案 0 :(得分:1)
您可以执行单个aggregation
来获得该结果。 mongo $lookup
文档的一部分显示how to lookup with an array。
鉴于以下集合:
db.user.insert({
name: "fred",
orders: [ObjectId("578d706916f07969c4b0cad2"),ObjectId("578d706916f07969c4b0cad3")]
})
db.order.insert({
_id: ObjectId("578d706916f07969c4b0cad2"),
date: ISODate("2012-12-20T06:01:17.171Z"),
items: ["a","b","c","d"]
})
db.order.insert({
_id: ObjectId("578d706916f07969c4b0cad3"),
date: ISODate("2012-12-19T06:01:17.171Z"),
items: ["x","y","z"]
})
使用以下内容执行aggregation
$unwind
数组的orders
$lookup
在order
字段_id
$unwind
新创建的orders
字段,其中包含已查找的项目$group
_id
并将您的orders
项重新组合在一个数组中,不会重复
聚合查询:
db.user.aggregate([{
$unwind: "$orders"
}, {
$lookup: {
from: "order",
localField: "orders",
foreignField: "_id",
as: "orders"
}
}, {
$unwind: "$orders"
}, {
$group: {
_id: "$_id",
name: {
$first: "$name"
},
orders: {
$addToSet: "$orders"
}
}
}])
这会给你:
{
"_id": ObjectId("5798a8e1968539bb0a98d1c3"),
"name": "fred",
"orders": [{
"_id": ObjectId("578d706916f07969c4b0cad3"),
"date": ISODate("2012-12-19T06:01:17.171Z"),
"items": ["x", "y", "z"]
}, {
"_id": ObjectId("578d706916f07969c4b0cad2"),
"date": ISODate("2012-12-20T06:01:17.171Z"),
"items": ["a", "b", "c", "d"]
}]
}