$ lookup返回一个空数组猫鼬

时间:2020-06-18 08:20:04

标签: node.js mongodb mongoose mongodb-query aggregation-framework

我将以下代码与$ lookup函数一起使用。

        postSchemaModel.aggregate([{
            "$geoNear": {
                "near": { "type": "Point", "coordinates": [6.7336665, 79.8994071], "Typology": "post" },
                "distanceField": "dist.calculated",
                "maxDistance": 5000,
                "includeLocs": "dist.location",
                "spherical": true
            }
        },
        { "$limit": limit },
        { "$skip": startIndex },
        { "$sort": { "createdAt": -1 } },
        {
            "$lookup": {
                "from": userSchemaModel.collection.name,
                "localField": "user_id",
                "foreignField": "_id",
                "as": "user_id"
            }
        },
        {
            "$project": {
                "post_data": 1,
                "likes": 1,
                "commentsCount": 1,
                "post_img": 1,
                "isUserLiked": 1,
                "usersLiked": 1,
                'exp_date': 1,
                "has_img": 1,
                "user_id": "$user_id",
                "typology": 1,
                "geometry": 1,
                "category": 1,
                "created": 1,
                "createdAt": 1,
                "updatedAt": 1,
            }
        },
    ]).then(async function(posts) {
        //some code here
    });

问题是这给了我 user_id 的空数组。以下是我收到的一个输出。

{ _id: 5ee1f89732fd2c33bccfec55,
    post_data: 'vvhhh',
    likes: 1,
    commentsCount: 0,
    post_img: null,
    isUserLiked: false,
    usersLiked: [ 5edf43b93859680cf815e577 ],
    exp_date: 2020-06-12T18:30:00.000Z,
    has_img: false,
    typology: 'chat',
    geometry:
     { pintype: 'Point',
       _id: 5ee1f89732fd2c33bccfec56,
       coordinates: [Array] },
    category: [],
    created: 1591867543468,
    createdAt: 2020-06-11T09:25:43.478Z,
    updatedAt: 2020-06-15T10:01:01.133Z,
    user_id: [] }

在我的情况下,我不希望它为null,并且希望得到如下所示的输出。

{ _id: 5ee1f89732fd2c33bccfec55,
post_data: 'vvhhh',
likes: 1,
commentsCount: 0,
post_img: null,
isUserLiked: false,
usersLiked: [ 5edf43b93859680cf815e577 ],
exp_date: 2020-06-12T18:30:00.000Z,
has_img: false,
typology: 'chat',
geometry:
 { pintype: 'Point',
   _id: 5ee1f89732fd2c33bccfec56,
   coordinates: [Array] },
category: [],
created: 1591867543468,
createdAt: 2020-06-11T09:25:43.478Z,
updatedAt: 2020-06-15T10:01:01.133Z,
user_id:  { img: 'default-user-profile-image.png',
   _id: 5edd103214ce223088a59236,
   user_name: 'Puka' }
}

我的userSchema如下所示

var userSchema = mongoose.Schema({
//some other fields
    user_name: {
        type: String,
        max: 30,
        min: 5
    },

    img: {
        type: String,
        default: 'default-user-profile-image.png'

    },
//some other fields
});
userSchema.plugin(uniqueValidator);
var userSchemaModel = mongoose.model('users', userSchema);

module.exports = {
    userSchemaModel,
}

根据这里的其他答案,我尝试使用 mongoose.Types.ObjectId(userId) ,但它给出了完整的空集。

这可能是问题所在,如果有人在几天之内坚持不懈,可以帮助我,这将非常有帮助。

更新: 发布架构

var postSchema = mongoose.Schema({
    user_id: {
        type: String,
        required: true,
        ref: 'users'
    },
//other fields
var postSchemaModel = mongoose.model('posts', postSchema);
module.exports = {
    postSchemaModel,
}

2 个答案:

答案 0 :(得分:1)

由于user._idObjectId)和post.user_idString)的数据类型不同,因此无法使用$lookup联接这些字段。在执行$lookup

之前,必须确保它们是相同的类型。

如果允许您更改架构,建议对ObjectId使用post.user_id

var postSchema = mongoose.Schema({
    user_id: {
        type: mongoose.Types.ObjectId,
        required: true,
        ref: 'users'
    },
    // ...other fields

但是请记住也将现有数据类型更改为ObjectId

如果出于某些原因真的不允许更改架构和现有数据。如果数据包含ObjectId的有效十六进制表示形式(可从MongoDB v4.0获得),则可以将post.user_id转换为ObjectId

[
// prior pipeline stages
{ "$sort": { "createdAt": -1 } },
{
  "$addFields": {
    "user_id": { "$toObjectId": "$user_id" }
  }
},
{
  "$lookup": {
    "from": userSchemaModel.collection.name,
    "localField": "user_id",
    "foreignField": "_id",
    "as": "user_id"
  }
},
// other stages        

答案 1 :(得分:-1)

由于mongodb中的_id字段存储为类型ObjectId,但是在posts集合中user_id存储为类型string,因此不是能够找到用户信息并带来空白数组。

要解决此问题,请在创建用户时在_id集合中保存user的纯字符串版本。例如

{ 
  _id: ObjectId("5ee1f89732fd2c33bccfec55"),
  doc_id: "5ee1f89732fd2c33bccfec55",
  //other user info
}

,然后在$ lookup中使用此doc_id字段

{
  "$lookup": {
      "from": userSchemaModel.collection.name,
      "localField": "user_id",
      "foreignField": "doc_id",
      "as": "user_id"
  }
}

通过这种方式,user_iddoc_id都将属于string类型,并且不需要任何类型转换麻烦。