Как мне отобразить только часть массива после findOne в MongoDB?

#node.js #arrays #mongodb #objectid

Вопрос:

Restaurants — это коллекция, в которой есть объекты, подобные приведенным ниже:

 {
    _id: new ObjectId("61723c7378b6d3a5a02d908e"),
    name: 'The Blue Hotel',
    location: 'Noon city, New York',
    phoneNumber: '122-536-7890',
    website: 'http://www.bluehotel.com',
    priceRange: '$

Я использую приведенный ниже код, чтобы найти этот объект на основе предоставленного идентификатора проверки

 async get(reviewId) {

    const restaurantsCollection = await restaurants();
    reviewId = ObjectId(reviewId)
    const r = await restaurantsCollection.findOne({reviews: {$elemMatch: {_id: reviewId}}})
    return r
 

Это возвращает весь объект из коллекции ресторанов, что мне делать, если я хочу, чтобы отображался только отзыв, идентификатор которого указан в get(reviewID)

Вывод:

 {
  _id: new ObjectId("61736a0f65b9931b9e428790"),
   title: 'dom',
   reviewer: 'firuu',
   rating: 4,
   dateOfReview: '25/1/2002',
   review: ' bruh'
}
 

Ответ №1:

С помощью проекции укажите поля, которые нужно возвращать

Следующее возвращает только обзор, идентификатор которого указан в get(reviewID)

 async get(reviewId) {
  const restaurantsCollection = await restaurants();
  reviewId = ObjectId(reviewId)

  const r = await restaurantsCollection.findOne(
    { reviews: { $elemMatch: { _id: reviewId } } },
    { "reviews.$": 1 }
  )

  return r
}
 

Тест здесь

Вы также можете использовать find вместо fineOne

Комментарии:

1. Он возвращает все обзоры, я хочу отобразить только соответствующий обзор

2. Привет, я обновил код. Пожалуйста, проверьте @swombhai

3. Я все равно получаю весь объект, когда возвращаю r, не уверен, почему

4. метод findOne узла js, насколько я знаю, принимает проекцию в качестве опции, поэтому его следует заменить на {"projection" : { "reviews.$": true }} test it maybe

5. Есть ли способ представить _id с помощью строки вместо new ObjectId? Можно ли добавить toString() в функцию findOne?

Ответ №2:

Запрос

  • замените ObjectId("61736a0f65b9931b9e428789") на reviewId
  • это вернет отзывы, соответствующие _id в массиве
  • если вы хотите получить только первый, в случае, если всегда есть максимум 1, вы можете заменить последний проект на {"$project": {"_id": 0, "review": {"$arrayElemAt": ["$reviews", 0]}}}

* не уверен, что это то, что вам нужно

Тестовый код здесь

 aggregate(
[{"$match": {"reviews._id": ObjectId("61736a0f65b9931b9e428789")}}
 {"$set": 
   {"reviews": 
     {"$filter": 
       {"input": "$reviews",
        "cond": 
        {"$eq": ["$this._id", ObjectId("61736a0f65b9931b9e428789")]}}}}},
  {"$project": {"_id": 0, "reviews": 1}}])
 

Комментарии:

1. Должен ли я куда-либо помещать toArray()? Я заменил код, но не получил результат

2. да, aggreagte вернет курсор, используйте result.toArray()

3. ответ @Pramisha больше похож на ваш код, я думаю, используйте другой ответ, это совокупное решение, здесь вы можете сделать это только с помощью find .

Ответ №3:

Возможно, это неправильный ответ на ваш вопрос, но вы можете попробовать что-то вроде этого.

 const r = await restaurantsCollection.findOne({reviews: {$elemMatch: {_id: reviewId}}})?.reviews.find(review => review._id.equals(reviewId))
 

,
cuisines: [ 'Mexican', 'Italian' ],
overallRating: 0,
serviceOptions: { dineIn: true, takeOut: true, delivery: true },
reviews: [
{
_id: new ObjectId("61736a0f65b9931b9e428789"),
title: 'asd',
reviewer: 'khoh',
rating: 3,
dateOfReview: '5/12/2002',
review: 'hey'
},
_id: new ObjectId("61736a0f65b9931b9e428790"),
title: 'dom',
reviewer: 'firuu',
rating: 4,
dateOfReview: '25/1/2002',
review: ' bruh'
}
]
}
Я использую приведенный ниже код, чтобы найти этот объект на основе предоставленного идентификатора проверки


Это возвращает весь объект из коллекции ресторанов, что мне делать, если я хочу, чтобы отображался только отзыв, идентификатор которого указан в get(reviewID)

Вывод:


Ответ №1:

С помощью проекции укажите поля, которые нужно возвращать

Следующее возвращает только обзор, идентификатор которого указан в get(reviewID)


Тест здесь

Вы также можете использовать find вместо fineOne

Комментарии:

1. Он возвращает все обзоры, я хочу отобразить только соответствующий обзор

2. Привет, я обновил код. Пожалуйста, проверьте @swombhai

3. Я все равно получаю весь объект, когда возвращаю r, не уверен, почему

4. метод findOne узла js, насколько я знаю, принимает проекцию в качестве опции, поэтому его следует заменить на {"projection" : { "reviews.$": true }} test it maybe

5. Есть ли способ представить _id с помощью строки вместо new ObjectId? Можно ли добавить toString() в функцию findOne?

Ответ №2:

Запрос

  • замените ObjectId("61736a0f65b9931b9e428789") на reviewId
  • это вернет отзывы, соответствующие _id в массиве
  • если вы хотите получить только первый, в случае, если всегда есть максимум 1, вы можете заменить последний проект на {"$project": {"_id": 0, "review": {"$arrayElemAt": ["$reviews", 0]}}}

* не уверен, что это то, что вам нужно

Тестовый код здесь


Комментарии:

1. Должен ли я куда-либо помещать toArray()? Я заменил код, но не получил результат

2. да, aggreagte вернет курсор, используйте result.toArray()

3. ответ @Pramisha больше похож на ваш код, я думаю, используйте другой ответ, это совокупное решение, здесь вы можете сделать это только с помощью find .

Ответ №3:

Возможно, это неправильный ответ на ваш вопрос, но вы можете попробовать что-то вроде этого.