Как мне сохранить реляционные данные в mon goose? - PullRequest
0 голосов
/ 24 февраля 2020

Как мне сохранить реляционные данные в пн goose?

Вложить ли я их?

Например, у меня есть схема для сохранения ресторанов. Каждый пользователь может оставить отзыв о ресторане. и тогда мне нужно отобразить средний рейтинг ресторана. Нужно ли вложить все отзывы в модель ресторана или нужно создать отдельную модель для рейтингов?

Какой подход лучше всего подходит для mongoDb?

Спасибо

1 Ответ

0 голосов
/ 24 февраля 2020

Я хотел бы начать с того, что , если ваш проект использует реляционные данные, я настоятельно рекомендую вам использовать реляционную базу данных вместо MongoDb . Я люблю Mongodb так же, как и следующего парня, и делал проекты в Mongodb, используя реляционные данные, но я столкнулся с проблемами, и я видел и слышал о слишком многих проектах, которые начинались с Mongodb, которые должны были go через болезненная миграция, когда проект стал слишком большим.

Однако, если вы настаиваете на использовании Mongodb, я бы сделал следующее:

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

Для целей этого ответа я высмеял некоторые JSON данные из Mockeroo (https://mockaroo.com/).

Давайте сначала придумаем некоторые базовые c детали для вашей схемы коллекции ресторана (модель).

{
  "_id": "Bujxd5U6k924D0M04NF2kOT6",
  "address": "Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.",
  "name": "Stringtough"
},
{
  "_id": "EA50k3O5vxEi543z949L6u8M",
  "address": "Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.",
  "name": "Zontrax"
},
{
  "_id": "LOs7NI67ijwH1g26e38067G0",
  "address": "Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.",
  "name": "Holdlamis"
}

Это только основные c детали, которые нам понадобятся для запроса среднего рейтинга; у вас, вероятно, гораздо больше деталей в вашей коллекции ресторанов.

Мы можем сгенерировать аналогичные данные для пользователей , где у каждого пользователя будет _id, name, email et c, но это не так слишком важен для целей этого ответа.

Теперь давайте перейдем к коллекции отзывов .

Когда пользователь просматривает ресторан, ему обычно требуется короткий параграф обзора и цифра c рейтинг. Я бы не высказался бы за вложение всех рецензий в массив, и, как вы упомянули в вопросе, создал бы другую коллекцию для хранения всех рецензий. Таким образом, наша коллекция "обзоров" будет выглядеть примерно так:

{
  "_id": "0M63HJQ9MKXR538084U92Zt2",
  "restaurant_id": "EA50k3O5vxEi543z949L6u8M",
  "user_id": "s0j45hXpv4tgCAl5vD8a2b87",
  "rating": 4.8,
  "review": "Maecenas tristique, est et tempus semper, est quam pharetra magna, ac consequat metus sapien ut nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris viverra diam vitae quam. Suspendisse potenti.\n\nNullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
  "date": "2019-06-03T06:36:19.000Z"
},
{
  "_id": "9K13616ouSn5H2o17l5Xp0x6",
  "restaurant_id": "LOs7NI67ijwH1g26e38067G0",
  "user_id": "RvYx1J1mU532iD3833286I7h",
  "rating": 2.3,
  "review": "Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.",
  "date": "2019-09-10T06:31:43.000Z"
},
{
  "_id": "754233Q64d553XguY2Vi28a2",
  "restaurant_id": "EA50k3O5vxEi543z949L6u8M",
  "user_id": "s0j45hXpv4tgCAl5vD8a2b87",
  "rating": 4.7,
  "review": "Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.\n\nCras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.",
  "date": "2019-06-04T02:17:01.000Z"
}, //and so on...

Обратите внимание, что между коллекциями "пользователи", "рестораны" и "отзывы" пары пользователей-отзывов и ресторанов-отзывов будут иметь одно отношения ко многим. Поэтому каждый документ в коллекции обзоров должен иметь restaurant_id и user_id (предпочтительно Mongodb ObjectIds), которые будут «внешними ключами» (своего рода) для других коллекций «restaurant» и «users». У каждого такого идентификатора будет только один, поскольку только один пользователь может написать конкретный отзыв, и что один отзыв не может быть написан для нескольких ресторанов. Затем, конечно, у нас есть поле «обзор», которое пишет пользователь, и «рейтинг», представляющий собой число с плавающей запятой, из 5.

Итак, скажем, у нас есть страница, где для каждого ресторана мы хотим отобразить название, количество отзывов и средний рейтинг. Как мы можем выполнить sh это?

Я написал следующий запрос агрегации для получения необходимых данных:

db.restaurants.aggregate([{
    $lookup: {
        from: "reviews",
        "let": {
            restaurant_id: "$_id"
        },
        pipeline: [{
                $match: {
                    $expr: {
                        $eq: [
                            "$restaurant_id",
                            "$$restaurant_id"
                        ]
                    }
                }
            },
            {
                $group: {
                    _id: null,
                    "number_of_ratings": {
                        $sum: 1
                    },
                    "average_rating": {
                        $avg: "$rating"
                    }
                }
            }
        ],
        as: "review_stats"
    }
},
{
    $unwind: {
        path: "$review_stats"
    }
},
{
    $unset: "review_stats._id"
}])

Результат должен выглядеть примерно так:

[{
    "_id": "Bujxd5U6k924D0M04NF2kOT6",
    "address": "Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.",
    "name": "Stringtough",
    "review_stats":
    {
        "average_rating": 3.1285714285714286,
        "number_of_ratings": 7
    }
},
{
    "_id": "EA50k3O5vxEi543z949L6u8M",
    "address": "Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.",
    "name": "Zontrax",
    "review_stats":
    {
        "average_rating": 4,
        "number_of_ratings": 4
    }
},
{
    "_id": "LOs7NI67ijwH1g26e38067G0",
    "address": "Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.",
    "name": "Holdlamis",
    "review_stats":
    {
        "average_rating": 2.325,
        "number_of_ratings": 4
    }
}]

Я настоятельно рекомендую вам попробовать его на Пн go Детская площадка (после издевательств над 3 ресторанными документами и 15 отзывами): https://mongoplayground.net/p/Pyfqus2w-fl

Есть другие запросы, которые могут быть легко получены с помощью этой схемы, например, просмотр всех ресторанов, просмотренных пользователем, получение исторических или недавних обзоров ресторана (с указанием определенного диапазона дат) и т. Д. c. Но для цели этого ответа я думаю, что этого достаточно. Надеюсь, вам понравилось, пожалуйста, не стесняйтесь указывать улучшения.

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