尝试使用此查询,返回查找为空
db.getCollection('tests').aggregate([
{$match: {typet:'Req'}},
{$project: {incharge:1}},
{$lookup:{
from: "users",
localField: "incharge", //this is the _id user from tests
foreignField: "_id", //this is the _id from users
as: "user"
}}
])
返回json
[
{
"_id": "57565d2e45bd27b012fc4db9",
"incharge": "549e0bb67371ecc804ad23ef",
"user": []
},
{
"_id": "57565d2045bd27b012fc4cbb",
"incharge": "549e0bb67371ecc804ad21ef",
"user": []
},
{
"_id": "57565d2245bd27b012fc4cc7",
"incharge": "549e0bb67371ecc804ad24ef",
"user": []
}
]
我尝试了这篇文章,但什么也没发生 MongoDB聚合项目字符串到ObjectId 并以此 MongoDB $lookup 使用 _id 作为 PHP 中的foreignField
更新
这是文档“用户”
{
"_id" : ObjectId("549e0bb67371ecc804ad24ef"),
"displayname" : "Jhon S."
},
{
"_id" : ObjectId("549e0bb67371ecc804ad21ef"),
"displayname" : "George F."
},
{
"_id" : ObjectId("549e0bb67371ecc804ad23ef"),
"displayname" : "Franc D."
}
我终于找到了解决方案,是我的猫鼬模式与ObjectId有问题
我改变这个
var Schema = new Schema({
name: { type: String, required: true},
incharge: { type: String, required: true},
});
有了这个
var Schema = new Schema({
name: { type: String, required: true},
incharge: { type: mongoose.Schema.ObjectId, required: true},
});
并且正在工作
首先,断言
incharge
字段的类型为mongoose.Schema.Types.ObjectId
。如果您仍然得到一个空数组,可能是因为您使用的是在 NodeJS 中声明的 schema 名称,而不是 MongoDB 使用的 collection 名称。
来自
UserSchema
文件的示例:
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const UserSchema = new Schema({
name: {
type: String,
required: true
},
incharge: {
type: Schema.Types.ObjectId,
required: true
},
})
const User = mongoose.model('User', UserSchema)
module.exports = User
上面的模型被 mongoose 命名为
User
,但 mongoDB 中相应的集合被命名为 users
。结果 $lookup
写为:
$lookup:{
from: "users", // name of mongoDB collection, NOT mongoose model
localField: "incharge", // referenced users _id in the tests collection
foreignField: "_id", // _id from users
as: "user" // output array in returned object
}
https://mongoosejs.com/docs/models.html
https://mongoosejs.com/docs/schematypes.html
将
string
与 ObjectId
进行比较不会引发错误,而是在聚合输出文档中发送一个空数组。所以你需要确保你已经将 string
对象 id 转换为 mongodb 的 ObjectId
:
db.getCollection('tests').aggregate([
{$match: {typet:'Req'}},
{$set: {incharge: {$toObjectId: "$incharge"} }}, // keep the whole document structure, but replace `incharge` into ObjectId
{$lookup:{
from: "users",
localField: "incharge", //this is the _id user from tests
foreignField: "_id", //this is the _id from users
as: "user"
}}
])
您只需使用
"_id.str"
,工作就会完成。
db.getCollection('tests').aggregate([
{$match: {typet:'Req'}},
{$project: {incharge:1}},
{$lookup:{
from: "users",
localField: "incharge", //this is the _id user from tests
foreignField: "_id.str", //this is the _id from users
as: "user"
}}
])
对我来说效果很好。
您的查找查询是正确的。但它试图将字符串类型(incharge)与ObjectId(_id)进行比较。将字符串转换为 ObjectId,如下所示。它对我有用。
db.getCollection('tests').aggregate([
{$match: {typet:'Req'}},
{$project: {
incharge:{
$toObjectId:"$incharge"
}
},
{$lookup:{
from: "users",
localField: "incharge", //this is the _id user from tests
foreignField: "_id", //this is the _id from users
as: "user"
}}
尝试将聚合函数中的负责人类型(字符串)更改为ObjectId 像这样
{
$project : {
incharge : {
$toObjectId : "$incharge"
}
}
}
您的查找查询是完美的,但问题是您将 incharge 作为字符串存储到数据库中,而 _id : ObjectId('theID') 是一个对象而不仅仅是字符串,您无法比较
string
(' ')带有 object
({ })。因此,最好的方法是将 incharge 键存储为对象(mongoose.Schema.ObjectId),而不是作为模式中的字符串。
如果你已经将key存储在字符串中,你可以使用$addFields(聚合)将key转换为objectId
{
"$addFields": {
incharge: {
"$toObjectId": "$incharge"
}
}
}
试试这个:
{
from: 'categories',
let: { cid: { $toObjectId: '$category_id' } },
pipeline: [
{ $match: { $expr: { $eq: ['$_id', '$$cid'] } } },
],
as: 'category_data'
}
即使它实际上在工作,它可能看起来失败的另一个原因:
国外馆藏部分文件已被删除,
因此您尝试匹配的 _id 字段不存在。
你的本地收藏已经存储了它们,但只是因为你的本地收藏中存在以下内容
customerId: ObjectId('d36257da015df161c577d0b6')
并不意味着它存在于您尝试 $lookup 的外国集合中
_id: ObjectId('d36257da015df161c577d0b6')
该文档已被删除,因此其_id不再存在。
....但您认为您的 $lookup 聚合有问题。