Запрос MongoDB объединяет две коллекции

Я пытаюсь сделать запрос к моему bbdd, чтобы получить информацию о двух коллекциях. Во-первых, у меня есть одна коллекция, называемая Collectables, которая представляет собой коллекцию, в которой хранятся все доступные элементы, которые один пользователь может получить с помощью приложения. Например, в этой коллекции может быть... 100 предметов. Это максимальное количество предметов. Это один документ из этой коллекции (так называемые предметы коллекционирования).

{
"_id" : ObjectId("5d387ecfbb676b173aa57fe3"),
"img" : "some url",
"name" : "La 5",
"__v" : 0,
"amount" : 17,
"available" : 16,
"collec" : ObjectId("5d36c0c34c86991db93bd7c8"),
"gen" : 3,
"metadata" : {},
"position" : 1
}

Затем у меня есть еще одна коллекция под названием AppUsers. В этой коллекции я храню всю информацию, связанную с пользователем. У каждого пользователя приложения здесь своя запись. Дело в том, что помимо метаинформации о пользователе, таких как псевдоним, аватар, возраст... у меня есть одно поле, называемое коллекционными предметами. Является массивом. Здесь я храню то, что коллекционируется у каждого пользователя. Например, если у одного пользователя есть 10 предметов коллекционирования (из другой коллекции), у меня есть 10 записей в этом массиве с этой информацией. Возможно, что один пользователь "выиграет" один и тот же предмет (предмет коллекционирования) дважды или более... поэтому в этой коллекции я храню поле подсчета с суммой. Например, пользователь выиграл предмет коллекционирования с идентификатором 1 в первый раз, поэтому я добавляю запись в массив со счетом 1. Если затем пользователь выиграет тот же предмет коллекционирования, количество будет равно 2... и так далее.

Это пример одного пользователя... с 3 предметами коллекционирования, но по несколько штук каждого предмета.

{
"_id" : ObjectId("5d36dc9445526a215c4eff52"),
"twitter" : "1",
"alias" : "ViktorCrowley",
"__v" : 25,
"collectables" : [ 
    {
        "count" : 12,
        "collectable" : ObjectId("5d36c1ba4c86991db93bd7e7")
    }, 
    {
        "count" : 25,
        "collectable" : ObjectId("5d36c13d4c86991db93bd7c9")
    }, 
    {
        "count" : 8,
        "collectable" : ObjectId("5d381e122f25221126a98f9c")
    }
   ]
}

Итак, в этом случае у этого пользователя, например, есть 3 разных предмета (предмета коллекционирования). Но представьте, что общее количество коллекционных предметов из первой коллекции равно 100.

Теперь... что я ищу. Мне нужен запрос, который дает мне (разбивку на страницы) элементы из первой коллекции (предметы коллекционирования), а в случае, если у пользователя уже есть один из этих предметов, помеченный общим количеством. Я имею в виду, что мне нужны все элементы из первой коллекции с новым полем под названием count. Если у пользователя нет записи в его массиве, счетчик будет равен 0, а если пользователь для этого предмета имеет, например, 4 предмета коллекционирования, счетчик будет равен 4. Что-то вроде этого:

[
{
"_id" : ObjectId("5d387ecfbb676b173aa57fe3"),
"img" : "some url",
"name" : "THe one",
"__v" : 0,
"amount" : 17,
"available" : 16,
"collec" : ObjectId("5d36c0c34c86991db93bd7c8"),
"gen" : 3,
"metadata" : {},
"position" : 1,
"count" : 0
},
{
"_id" : ObjectId("5d387ecfbb676b173aa57fe3"),
"img" : "some url",
"name" : "The two",
"__v" : 0,
"amount" : 17,
"available" : 16,
"collec" : ObjectId("5d36c0c34c86991db93bd7c8"),
"gen" : 3,
"metadata" : {},
"position" : 2,
"count" : 1
},
{
"_id" : ObjectId("5d387ecfbb676b173aa57fe4"),
"img" : "some url",
"name" : "The Three",
"__v" : 0,
"amount" : 17,
"available" : 16,
"collec" : ObjectId("5d36c0c34c86991db93bd7c8"),
"gen" : 3,
"metadata" : {},
"position" : 3,
"count" : 0
},
{
"_id" : ObjectId("5d387ecfbb676b173aa57fe4"),
"img" : "Some url",
"name" : "La 5",
"__v" : 0,
"amount" : 17,
"available" : 16,
"collec" : ObjectId("5d36c0c34c86991db93bd7c8"),
"gen" : 3,
"metadata" : {},
"position" : 4,
"count" : 12
}

Я пробовал несколько вещей, используя агрегат и поиск, но я не могу заставить это работать.

Единственное, что я мог получить, это получить информацию от AppUser и общее количество.

Примерно так (с мангустом):

AppUser.aggregate([
    { $match: matchQuery },
    {$unwind: "$collectables"},

    {
        $lookup: 
        {
            from: "collectables",
            localField: "collectables.collectable",
            foreignField: "_id",
            as: "result"
        }
    },
    { $sort: { "result.position": 1 } },
    {$unwind: "$result"},
    { $addFields : { "result.count" : "$collectables.count" } 
},
    { $replaceRoot: { newRoot: "$result" } },
    { $skip: size * (page - 1) },
    { $limit: size }
 ]).exec((err, result) => 
{
    if (err) 
    {
        console.info(err);
        return res.status(401).send({ success: false });
    }
    else {
        return res.status(200).send({ success: true, result });
    }

});

Так что мне нужна помощь, потому что у меня три дня с этим, и я не могу получить что-нибудь хорошее... Заранее спасибо...

что у вас есть в matchQuery? Это основано на конкретном? Если это основано на пользователе, то почему вы выполняете его для сбора пользователей и возвращаете данные о предметах коллекционирования? Вам нужен исходный пользовательский документ плюс поле со списком всех связанных данных о предметах коллекционирования с соответствующим количеством предметов коллекционирования?

whoami - fakeFaceTrueSoul 29.07.2019 03:25

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

Roberto Gutierrez 29.07.2019 08:45
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Ниже запрос принесет нам ожидаемый результат

db.appuser.aggregate([
  { $unwind: "$collectables" },
  {
    $lookup: {
      from: "collectables",
      localField: "collectables.collectable",
      foreignField: "_id",
      as: "result"
    }
  },
  {
    $project: { 
      result: 1,
      flag: { "$gt": [ {"$size": "$result"}, 0 ] },
      "collectables.count": 1,
      alias: 1,
      _id: 0
    }
  },
  {
    $match: { flag: true }
  }
]);

Раскрутите массив appuser.collectables, затем выполните поиск между коллекциями collectables и appuser, затем используйте $project и $match, чтобы получить желаемый результат.

На этапе $project добавлен флаг для фильтрации нужных документов путем проверки размера результирующего массива вывода $lookup.

Используемые образцы данных

db.collectables.find()


{
  "_id": "5d387ecfbb676b173aa57fe3",
  "img": "some url",
  "name": "La 5",
  "__v": 0,
  "amount": 17,
  "available": 16,
  "collec": "5d36c0c34c86991db93bd7c8",
  "gen": 3,
  "metadata": {

  },
  "position": 1
}

db.appuser.find()

[{
  "_id": "5d36dc9445526a215c4eff52",
  "twitter": "1",
  "alias": "ViktorCrowley",
  "__v": 25,
  "collectables": [
    {
      "count": 12,
      "collectable": "5d36c1ba4c86991db93bd7e7"
    },
    {
      "count": 25,
      "collectable": "5d36c13d4c86991db93bd7c9"
    },
    {
      "count": 8,
      "collectable": "5d381e122f25221126a98f9c"
    }
  ]
},
{
  "_id": "5d36dc9445526a215c4efga1",
  "twitter": "1",
  "alias": "John",
  "__v": 11,
  "collectables": [
    {
      "count": 10,
      "collectable": "5d387ecfbb676b173aa57fe3"
    }
  ]
},
{
  "_id": "6dc2dc9445526a215c4efga1",
  "twitter": "1",
  "alias": "Alice",
  "__v": 11,
  "collectables": [
    {
      "count": 25,
      "collectable": "5d387ecfbb676b173aa57fe3"
    },
    {
      "count": 3,
      "collectable": "5d36c13d4c86991db9312349"
    },
    {
      "count": 5,
      "collectable": "5d381e122f25221126a9711c"
    }
  ]
}]

Окончательный результат

{
  "alias": "John",
  "collectables": {
    "count": 10
  },
  "result": [
    {
      "_id": "5d387ecfbb676b173aa57fe3",
      "img": "some url",
      "name": "La 5",
      "__v": 0,
      "amount": 17,
      "available": 16,
      "collec": "5d36c0c34c86991db93bd7c8",
      "gen": 3,
      "metadata": {

      },
      "position": 1
    }
  ],
  "flag": true
}
{
  "alias": "Alice",
  "collectables": {
    "count": 25
  },
  "result": [
    {
      "_id": "5d387ecfbb676b173aa57fe3",
      "img": "some url",
      "name": "La 5",
      "__v": 0,
      "amount": 17,
      "available": 16,
      "collec": "5d36c0c34c86991db93bd7c8",
      "gen": 3,
      "metadata": {

      },
      "position": 1
    }
  ],
  "flag": true
}

Надеюсь, поможет!

@RobertoGutierrez - Вы можете пометить его как ответ, чтобы он помог другим

Clement Amarnath 31.07.2019 12:16

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