如何解决如何在同一查询中从当前集合中获取对象数组以及另一集合中的数据
我有一个用户集合。每个用户可以有多个朋友,其_id值存储在用户文档的数组中。
我想呈现一个列表,该列表包含用户的朋友名称列表,并且在每个个人名称下我都希望有一个位置,但是这些位置在另一个文档中,因为每个用户可以有多个位置,并且数量不受限制,例如他们去过的地方/最喜欢的地方。
这些是孤立的2个查询,但我需要以某种方式将它们组合起来。
这是一个查询,它查看用户的朋友数组中的用户ID值,然后根据该ID获取相关的用户信息。
friends = await User.findOne({ _id: userId })
.populate("friends","name mobile",null,{ sort: { name: 1 } })
.exec();
然后,获取特定用户的位置:
const place = await Place.find({ creator: userId });
所以,我基本上想循环列出朋友,每个朋友的名字都在他们的名字下,例如:
Joe Soap
- London Bridge
- Eiffel Tower
Bob Builder
- Marienplatz
mongoDb中的数据如下:
用户:
{
"_id": {
"$oid": "5f2d9ec5053d4a754d6790e8"
},"friends": [{
"$oid": "5f2da51e053e4a754d5790ec"
},{
"$oid": "5f2da52e053d4a754d6790ed"
}],"name": "Bob","email": "bob@gmail.com","created_at": {
"$date": "2020-08-07T18:34:45.781Z"
}
}
地点:
{
"_id": {
"$oid": "5f3695d79864bd6c7c94e38a"
},"location": {
"latitude": -12.345678,"longitude": 12.345678
},"creator": {
"$oid": "5f2da51e053e4a754d5790ec"
},}
第一次连接基本上是从同一用户集合内的数组获取数据。第二个是从另一个集合(地方)获取数据。
更新:几乎可以正常工作
friends = await User.aggregate([
{ $match: { _id: new mongoose.Types.ObjectId(userId) } },{
$lookup: {
from: "users",localField: "friends",foreignField: "_id",as: "friends_names",},{ $unwind: "$friends_names" },{
$lookup: {
from: "places",foreignField: "creator",as: "friends_places",{ $unwind: "$friends_places" },{
$project: {
"friends_names.name": 1,"friends_places.saved_at": 1,]);
返回的数据:
[
{
_id: 5f2d9ec5053d4a754d6790e8,friends_names: { name: 'Bob' },friends_places: { saved_at: 2020-08-17T13:40:28.334Z }
},{
_id: 5f2d9ec5053d4a754d6790e8,friends_names: { name: 'Natalie' },friends_places: { saved_at: 2020-08-17T13:40:28.334Z }
}
]
解决方法
编辑,好的,我相信我已经正确地反向工程了您的最小架构:
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/test",{ useNewUrlParser: true });
mongoose.set("debug",true);
const db = mongoose.connection;
db.on("error",console.error.bind(console,"connection error:"));
db.once("open",async function () {
await mongoose.connection.db.dropDatabase();
// we're connected!
console.log("Connected");
const userSchema = new mongoose.Schema({
friends: [{ type: mongoose.Schema.Types.ObjectId,ref: "User" }],name: String,});
const placesSchema = new mongoose.Schema({
latitude: String,creator: { type: mongoose.Schema.Types.ObjectId,ref: "User" },});
const User = mongoose.model("User",userSchema);
const Place = mongoose.model("Place",placesSchema);
const bob = new User({ name: "Bob",friends: [] });
await bob.save();
const natalie = new User({ name: "Natalie",friends: [bob] });
await natalie.save();
//const chris = new User({ name: "Chris",friends: [] });
//await chris.save();
const john = new User({ name: "John",friends: [natalie,bob] });
await john.save();
const place1 = new Place({ latitude: "Place1",creator: bob });
const place3 = new Place({ latitude: "Place3",creator: bob });
const place2 = new Place({ latitude: "Place2",creator: natalie });
await place1.save();
await place2.save();
await place3.save();
await User.find(function (err,users) {
if (err) return console.error(err);
console.log(users);
});
await Place.find(function (err,places) {
if (err) return console.error(err);
//console.log(places);
});
var cc = await mongoose
.model("User")
.aggregate([
{ $match: { _id: john._id } },{ $unwind: "$friends" },{
$lookup: {
from: "places",localField: "friends",foreignField: "creator",as: "friends_places",}
},{ $lookup: {from: 'users',localField: 'friends',foreignField: '_id',as: 'friend_name'} },//,{ $include: 'friends' }
{ $unwind: "$friends_places" },{ $unwind: "$friend_name" }//,{ $skip: 1},{$limit: 1}
])
.exec();
console.log(cc);
});
这是最相关的部分:
var cc = await mongoose
.model("User")
.aggregate([
{ $match: { _id: john._id } },{$limit: 1}
])
.exec();
最初的unwind: friends
首先对集合进行“拼合”。因此,基本上我们有了'userId |每个用户和朋友的FriendId。然后,对于每一行,我们只需查找他创建的位置($ lookup)。最后,我们放宽friends_places,因为我们不希望它们在控制台输出中呈现为[object]。另外,这里$match
,因为我们只想检查一个用户的朋友的位置。考虑到我们也想知道朋友的名字,我们必须再做一个join
-这就是为什么第二个$lookup
的原因。之后,简单的$unwind
就可以获取朋友的详细信息。
代码产生以下内容:
[ { _id: 5f3aa3a9c6140e3344c78a45,friends: 5f3aa3a9c6140e3344c78a44,name: 'John',__v: 0,friends_places:
{ _id: 5f3aa3a9c6140e3344c78a48,latitude: 'Place2',creator: 5f3aa3a9c6140e3344c78a44,__v: 0 },friend_name:
{ _id: 5f3aa3a9c6140e3344c78a44,friends: [Array],name: 'Natalie',__v: 0 } },{ _id: 5f3aa3a9c6140e3344c78a45,friends: 5f3aa3a9c6140e3344c78a43,friends_places:
{ _id: 5f3aa3a9c6140e3344c78a46,latitude: 'Place1',creator: 5f3aa3a9c6140e3344c78a43,friend_name:
{ _id: 5f3aa3a9c6140e3344c78a43,friends: [],name: 'Bob',friends_places:
{ _id: 5f3aa3a9c6140e3344c78a47,latitude: 'Place3',__v: 0 } } ]
所以,我们得到了约翰朋友的住所的简单清单。
重要位:from: places
中的$lookup
是至关重要的,因为我们必须使用MongoDB的集合名称,而不是模型名称1。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。