Запрос MongoDB с массивом идентификаторов

#node.js #arrays #mongodb #express

#node.js #массивы #mongodb #выразить

Вопрос:

У меня есть эта коллекция:

 {
        "_id": "5f1bd6c7d90cb03e845adbbf",
        "name": "John Doe",
        "likes": [
            {
                "_id": "5f378b105d337347e8958a50",
                "user": "5f357ac9c0d2019cc82b5a2f",
                "post": "5f3032894cd4a000175d333c",
            },
            {
                "_id": "5f354e351a98dd7c7081d72d",
                "user": "5f357ac9c0d2019cc82b5a2f",
                "post": "5f3bf7a44ed4f031bc575c2b"
            },
            {
                "_id": "5f354cc2879f8a81b0ab28fe",
                "user": "5f30380288a63e001755401e",
                "post": "5f310ce5e18bad001792fb60"
            }
        ]
  

Теперь я хочу найти все записи, которые соответствуют идентификаторам likes.post.

Это работает, но, очевидно, дает мне только одно сообщение:

 const posts = await Post.find({ _id: [user.likes[0].post] });
res.json(posts);
  

Я попробовал цикл for, но он возвращает только одно сообщение. Когда я регистрирую это в консоли, я получаю все записи, которые соответствуют:

 for (let i = 0; i < user.likes.length; i  ) {
  const posts = await Post.find({ _id: [user.likes[i].post] });
  res.json(posts);
}
  

Ответ №1:

Вы можете сделать это с помощью $in оператора.

 const posts = await Post.find({ _id: { $in: user.likes.map(l => l.post) } });
res.json(posts);
  

Документ

Ответ №2:

Я попробовал цикл for, но он возвращает только одно сообщение. Когда я регистрирую это в консоли, я получаю все записи, которые соответствуют:

Построение цикла завершается с ошибкой, потому что вы отправляете ответ после первой итерации, и соединение закрывается. Вот как это исправить:

 const posts = [];
for (let i = 0; i < user.likes.length; i  ) {
  const post = await Post.find({ _id: [user.likes[i].post] });
  posts.push(post)
}

res.json(posts)
  

Или используйте карту, подобную этой:

 const postPromises = user.likes.map(({ post }) => {
  return Post.find({ _id: [user.likes[i].post] });
})

const posts = Promise.all(postPromises);
res.json(post)
  

Но тогда, вместо выполнения двух отдельных запросов, вы можете изменить любой запрос, который вы запускаете, чтобы получить этот документ.
Предполагая, что вы используете mongoose:

 Author
  .findOne({ name: 'John Doe' })
  .populate({
    path: 'likes',
    populate: { path: 'post' }
  })
;
  

Я в пути и не могу протестировать это сейчас, но если это не удастся, попробуйте это вместо:

 Author
  .findOne({ name: 'John Doe' })
  .populate('likes.post')
;