Простой $lookup «левое соединение» ObjectId двух коллекций не работает в Mongo DB

Я использую Mongo DB Atlas с node.js и oboe (oboe передает результаты в html). Я новичок во всем этом, просто изучаю все эти технологии, поэтому объяснение в более простых терминах будет оценено.

Цель состоит в том, чтобы выполнить $lookup между двумя коллекциями, в данном случае между коллекцией «обзор» и «место». Я исследовал похожие ответы, но они либо не работали, либо использовали строки, а не ObjectId.

Это довольно просто, просто соедините ObjectId обеих коллекций, но я не могу вытащить данные из «связанной слева» коллекции «мест» при использовании гобоя (см. Код гобоя внизу, FWIW).

Вот посмотрите на документ из обеих коллекций, затем код. Что я делаю не так? Я попытался преобразовать их в строки и объединить с .toString() и .str, а также поставить «place_id.ObjectId» и «_id.ObjectId» для localField и ForeignField. Другое дело, как я могу увидеть, что находится в курсоре, чтобы знать, что я получаю? отладка (курсор.ToArray()) не работает. Заранее спасибо.

review
({
  "_id": { "$oid": "5fd27fd9647f7bb815c4c946" },
  "place_id": { "$oid": "5fbc37c4fc13ae680b00002b" }, // connect this...
  "user_id": { "$oid": "5fbc10ecfc13ae232d000068" },
  "title": "Black Forest -- unforgettable!",
  "description": "The forest was great.",
  "score": { "$numberInt": "5" }
}


place
{
  "_id": { "$oid": "5fbc37c4fc13ae680b00002b" }, // connected to _id above
  "name": "Black Forest (Schwarzwald)",
  "category": "activity",
  "city": "Freiburg",
  "country": "Germany",
  "description": "The Black Forest (German: Schwarzwald [ˈʃvaʁtsvalt] (About this soundlisten)) is a large forested mountain range.]",
  "image": { "filename": "1607629020164_black_forest.jpg", "mime": "image/jpeg" },
  "state": ""
})

router.get('/', async (req, res, next) => {
  debug('get all reviews api');
  try {
    const q = req.query.q;
    const collation = { locale: 'en_US', strength: 1 };

    const matchStage = {};
    if (q) {
      matchStage.$text = { $search: q };
    }
    const pipeline = [
      {
        $match: matchStage,
      },
      {
        $lookup: {
          from: 'place',
          localField: 'place_id',
          foreignField: '_id',
          as: 'place',
        },
      },
    ];
    const connection = await db.connect();
    const cursor = connection.collection('review').aggregate(pipeline, { collation: collation });


    // write the JSON file
    res.type('application/json');
    res.write('[\n');
    for await (const doc of cursor) {
      res.write(JSON.stringify(doc));
      res.write(',\n');
    }
    res.end('null]');
  } catch (err) {
    sendError(err, res);
  }
});

Курсор перемещается на гобой и становится «предметом». Я бы ожидал использовать строку шаблона, такую ​​​​как {item.place.name}, чтобы получить данные при вводе этого в html. Вот как бы я получил к нему доступ, верно?

    const performSearch = () => {
      seen = 0;
      $('stream-data-spinner').removeClass('d-none');
      $('#search-results').html('');
      const formData = $('#search-place-form').serialize();

      oboe('/api/review?' + formData)
        .node('![*]', (item) => {
          if (item) {
            chunk.push(item);
            if (chunk.length >= 1000) {
              showChunk(chunk);
            }
          }
          return oboe.drop;
        })
        .done((_) => {
          // show the last chunk
          showChunk(chunk);
          // hide the spinner
          outputSpinner.classList.add('d-none');
        })
        .fail((res) => {
          // show the error
          outputSeen.textContent = `ERROR: network error`;
          outputSeen.classList.add('text-danger');
          outputSpinner.classList.add('text-danger');
        });
    };

Вы обязательно должны использовать Atlas Search для этого запроса. У вас там есть бесплатная учетная запись Sandbox? Я могу написать запрос.

Nice-Guy 11.12.2020 05:15

У меня есть наборы образцов данных, если вы это имеете в виду, например, в одном из них есть фиктивные данные airbnb. Тем не менее, я считаю, что мой $lookup работает, потому что я вижу JSON.tringify в отладке, но я не могу получить доступ к нужным мне данным в том, что результаты выводятся в oboe. Я думаю, что ответ Рэя ниже может быть правильным путем, который мне нужно использовать $ unwind. Я бы очень хотел, чтобы вы написали запрос.

Paul W 11.12.2020 05:22

Я считаю, что у меня это есть, см. Решение Рэя, $unwind сделал это за меня.

Paul W 11.12.2020 05:28

О, вы искали левое соединение? Виноват. Я просто просматривал все элементы с тегами MongoDB, которые включали $search. Для многих операций поиска $search как первый этап агрегации быстрее. Этот случай уникален, и я, честно говоря, не прочитал его достаточно. Я напишу запрос. Одну секунду.

Nice-Guy 11.12.2020 05:37

Что ж, похоже, вам потребуются два запроса, потому что вы хотите объединить две коллекции, если только вы не объединили их с материализованными представлениями. Ты на 4.4?

Nice-Guy 11.12.2020 05:38
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
182
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Из вашего запроса агрегации MongoDB ваше поле place представляет собой массив. Вы можете $unwind сгладить его в объект, чтобы ваш код гобоя мог получить к нему доступ.

Читаю о $unwind сейчас. Сейчас я использую гобой и безрезультатно пишу всевозможные странные шаблонные строки, такие как ${item.place[0].city и несколько других вариантов. Похоже ли, что $unwind по-прежнему является решением?

Paul W 11.12.2020 05:23

Вот оно. Просто добавил после поиска: `` { $unwind: '$place', },` `` и это сделало работу.

Paul W 11.12.2020 05:27

Я думаю, это зависит от того, как вы используете результат агрегации. Исходя из моего опыта, я не предпочитаю хранить поля в виде массива, так как хочу избежать тяжелой обработки полей массива. Код станет запутанным и может быть неэффективным. Обычно я раскручиваю их после $lookup, чтобы использовать оптимизацию $lookup + $unwind.

ray 11.12.2020 05:32

Другие вопросы по теме