$ lookup возвращает пустой массив mongoose - PullRequest
1 голос
/ 18 июня 2020

Я использую следующий код с функцией поиска.

        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: [] }

В моем случае я не хочу, чтобы он был нулевым, и ожидаю вывода, как показано ниже.

{ _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,
}

Согласно другим ответам здесь я попытался использовать mon goose .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 ]

1 голос
/ 18 июня 2020

Поскольку типы данных user._id (ObjectId) и post.user_id (String) не совпадают, вы не можете объединить эти поля, используя $lookup. Вы должны убедиться, что они одного типа, прежде чем делать $lookup

Если вам разрешено изменять схему, рекомендуется использовать ObjectId для post.user_id

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

Но не забудьте также изменить существующий тип данных на ObjectId.

Если вам действительно не разрешено изменять схему и существующие данные по какой-то причине. Вы можете преобразовать post.user_id в ObjectId, если данные содержат допустимое шестнадцатеричное представление ObjectId (доступно в MongoDB v4.0)

[
// 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        
0 голосов
/ 18 июня 2020

Поскольку поле _id в mongodb хранится как тип ObjectId, но в коллекции posts user_id хранится как тип string, поэтому он не может найти информацию о пользователе и вывести пустой массив.

Чтобы решить эту проблему, сохраните версию _id в виде простой строки в коллекции user при создании пользователя. например,

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

, а затем используйте это поле doc_id в $ lookup

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

Таким образом, как user_id, так и doc_id будут иметь тип string и не потребуется никаких проблем с преобразованием типов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...