Присоединяйтесь к коллекции через UUID, используя mongoose

Мой проект разработан в Express JS. Я столкнулся с проблемой уже давно. Я хочу объединить 2 коллекции по user_id (от продуктов) и _id (от пользователей). Обратите внимание, что _id — это UUID. Это работает для других полей. Но когда я пытаюсь установить связь с _id, он возвращает пустой массив.

Название коллекции — продукты

{
  "_id": {
    "$oid": "62414fc1d2564b4554hj0"
  },
  "amountIsFixed": false,
  "amount": 10,
  "active": false,
  "user_id": "62414fc1d24545456d4957ec"
}

имя коллекции — пользователи

{
  "_id": {
    "$oid": "62414fc1d24545456d4957ec"
  },
  "fullname": "Test"
}

Моя кодовая база

const respPromise = Product.aggregate([
        
      {
        $lookup: {
          from: 'users',
          localField: 'user_id',
          foreignField: '_id',
          as: 'userDetails'
        }
      },
      {
  $unwind: "$userDetails"
   },
    {
        $project: { 
            fullname: "$userDetails.fullname",
            id: "$userDetails.id",
            amount: 1
        }
    }
      ]);

 let resp = await respPromise ;

В моей базе данных Mongo существуют соответствующие данные. Но он возвращается пустым. Я хочу получить соответствующие данные. Причина того, что я выяснил "_id". Потому что, если я установил связь с другой областью, это работает.

Как я могу установить связь с _id.

заранее спасибо

🤔 А знаете ли вы, что...
Node.js поддерживает работу с WebSocket для двусторонней связи между клиентом и сервером.


1
121
1

Ответ:

Решено

Ваш Product.user_id относится к типу String, тогда как ваш User._id относится к типу ObjectId.

Это означает, что когда вы выполняете $lookup, localField: 'user_id' не соответствует ни одному foreignField: '_id', поскольку существует несоответствие типов.

Лучший вариант — переопределить схему Product так, чтобы user_id стало ObjectId. Однако, если вы не можете этого сделать, вы можете добавить в свою агрегацию поле, которое просто преобразует user_id в ObjectId и использовать его вместо localField.

Это может выглядеть так:

const resp = await Product.aggregate([
  {
    $set: {
      user_ob_id: {
        $toObjectId: "$user_id" //< Convert here
      }
    }
  },
  {
    $lookup: {
      from: "users",
      localField: "user_ob_id", //< Use the new field in the lookup
      foreignField: "_id",
      as: "userDetails"
    }
  },
  {
    $unwind: "$userDetails"
  },
  {
    $project: {
      fullname: "$userDetails.fullname",
      id: "$userDetails.id",
      amount: 1
    }
  }
])

Рабочий пример смотрите ЗДЕСЬ.

Примечание. В вашем примере данных "62414fc1d2564b4554hj0" недопустимо ObjectId. Не уверен, что это была опечатка, когда вы вставляли сюда.