Mongodb $lookup 不使用 _id

Posted

技术标签:

【中文标题】Mongodb $lookup 不使用 _id【英文标题】:Mongodb $lookup Not working with _id 【发布时间】:2016-10-08 21:35:45 【问题描述】:

尝试使用此查询,返回查找为空

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 aggregation project string to ObjectId 有了这个 MongoDB $lookup with _id as a foreignField in php

更新

这是文档“用户”

    
        "_id" : ObjectId("549e0bb67371ecc804ad24ef"),
        "displayname" : "Jhon S."
    ,
    
        "_id" : ObjectId("549e0bb67371ecc804ad21ef"),
        "displayname" : "George F."
    ,
    
        "_id" : ObjectId("549e0bb67371ecc804ad23ef"),
        "displayname" : "Franc D."
    

【问题讨论】:

请发布文档示例,因为这将帮助我们帮助您:-) 感谢人添加文档用户 【参考方案1】:

我终于找到了解决方案,是我在猫鼬中使用 ObjectId 的 Schema 的问题

我改这个

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,
);

并且正在工作

【讨论】:

我的两个 ID 都是猫鼬对象 ID,但我仍然得到空数组 它返回空数组 能否请您告诉如何在 Shell 上执行此操作 对此我感激不尽!我这辈子都搞不定。干得好!【参考方案2】:

首先,断言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.htmlhttps://mongoosejs.com/docs/schematypes.html

【讨论】:

一个人为我改变了一切【参考方案3】:

比较stringObjectId 不会引发错误,而是在聚合输出文档中发送一个空数组。所以你需要确保你已经将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"
    
])

【讨论】:

对我来说就像一个魅力。我可以确认这行得通【参考方案4】:

您的查找查询是正确的。但它试图将字符串类型(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"

【讨论】:

【参考方案5】:

您只需使用"_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"

])

对我来说很好。

【讨论】:

非常感谢,它有效,但我有点不同。 foreignField: "_id".toString(), //这是用户的_id【参考方案6】:

尝试在聚合函数中将字符串类型更改为 ObjectId 像这样

 
    $project : 
        incharge : 
            $toObjectId : "$incharge"
        
    

【讨论】:

【参考方案7】:

您的查找查询是完美的,但问题是您将 incharge 作为字符串存储到数据库中,而 _id : ObjectId('theID') 是一个对象,而不仅仅是字符串,您不能将 string (' ') 与 object ( ) 进行比较。因此,最好的方法是将 incharge 键存储为对象(mongoose.Schema.ObjectId),而不是模式中的字符串。

【讨论】:

以上是关于Mongodb $lookup 不使用 _id的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB $lookup 在 2 级嵌套文档上不使用 $unwind

Mongodb $lookup 使用多个条件 mongodb

MongoDB 聚合 - 我如何“$lookup”嵌套文档“_id”?

使用 $lookup 和 let 和管道在 MongoDB 中声明变量

MongoDB $lookup 和 $group 返回空数组

MongoDb:聚合 $lookup