我正在开发一个聊天应用程序,我在DB中保存对话列表,像这样;
对话集合:
{
members: [ "123", "456" ]
...rest
}
和用户集合:
{
_id: ObjectId( "123" ), name: "anyone"
},
{
_id: ObjectId( "456" ), name: "someone"
}
我想要的结果是:
{
members: [
{_id: ObjectId( "123" ), name: "anyone"},
{_id: ObjectId( "456" ), name: someone"}
]
}
我知道聚合查找是救援,但无法找到一种方法如何从该成员的数组中获取所有id,因为在未来它可以是20到30个id。如果它是一个简单的字段,那么我可以获取,但对于数组,我不能。
我已经试过了
db.conversations.aggregate([
{
"$lookup": {
"from": "users",
"localField": "members",
"foreignField": "_id",
"as": "members_details"
}
}
])
但是它返回members_details: []
您可以使用下面的查询来完成您想要的。您需要使用$lookup
,因为您希望从不同的集合收集数据,而不是当前查询的集合。
你可以在这里查看一个现场演示
这是一个更新的实时演示
数据库db={
"conversations": [
{
members: [
123,
456
]
}
],
"users": [
{
"_id": 123,
"name": "foo"
},
{
"_id": 456,
"name": "bar"
}
]
}
查询db.conversations.aggregate([
{
"$lookup": {
"from": "users",
"localField": "members",
"foreignField": "_id",
"as": "members"
}
},
{
$project: {
_id: 0,
members: 1
}
}
])
结果[
{
"members": [
{
"_id": 123,
"name": "foo"
},
{
"_id": 456,
"name": "bar"
}
]
}
]
<标题>更新在这里查看新的实时演示
新的查询
db.conversations.aggregate([
{
$unwind: "$members"
},
{
"$lookup": {
"from": "users",
"as": "membersFlat",
"let": {
memberObjectId: {
"$toObjectId": "$members"
}
},
pipeline: [
{
$match: {
$expr: {
$eq: [
"$$memberObjectId",
"$_id"
]
}
}
}
]
}
},
{
$group: {
_id: null,
members: {
$push: {
"_id": {
$first: "$membersFlat._id"
},
"name": {
$first: "$membersFlat.name"
}
}
}
}
},
{
$project: {
_id: 0
}
}
])
新结果[
{
"members": [
{
"_id": ObjectId("124578987898787845658574"),
"name": "foo"
},
{
"_id": ObjectId("124578986532124578986532"),
"name": "bar"
}
]
}
]
标题>由于您的members
id是会话集合中的字符串,您可以将其转换为对象id和连接到用户集合,
$addFields
更新members
数组$map
循环members
数组$toObjectId
将字符串对象id类型转换为对象id类型
db.conversations.aggregate([
{
$addFields: {
members: {
$map: {
input: "$members",
in: {
$toObjectId: "$$this"
}
}
}
}
},
{
$lookup: {
from: "users",
localField: "members",
foreignField: "_id",
as: "members"
}
}
])
游乐场
您可以像这样使用普通的.find()
:
const members = [
ObjectId('4ed3ede8844f0f351100000c'),
ObjectId('4ed3f117a844e0471100000d'),
ObjectId('4ed3f18132f50c491100000e')
]
const docs = await model.find({
'_id': { $in: members }
}).exec()
安装猫鼬自动种群。在你的模型代码
import {Schema, model} from 'mongoose';
const modelSchema = new Schema({
...
chats: [{type: Schema.Types.ObjectId, ref: "Chat", autopopulate: true}]
})
modelSchema.plugin(require('mongoose-autopopulate'));
...