Присоединяйтесь, как в mongodb, с массивами документов и условий

#mongodb #aggregation-framework

Вопрос:

Я изо всех сил пытаюсь создать запрос MongoDB для использования агрегации для выполнения соединения, подобного запросу с условиями. Это мой вклад :

Коллекция «Вещи» :

 {
    _id : 1
    users : [
        {
            userId : 00001,
            role : "creator"
        },
        {
            userId : 00002,
            role : "spectator"
        }
    ]
}
{
    _id : 2
    users : [
        {
            userId : 00002,
            role : "creator"
        },
        {
            userId : 00001,
            role : "spectator"
        }
    ]
}
 

Коллекция «Пользователи» :

 {
    _id : 00001,
    name : "John"
}
{
    _id : 00002,
    name : "Doe"
}
 

Я хочу получить имя/информацию создателя для данной «Вещи» _id и получить что-то подобное для _id = 1:

 {
    _id : 00001,
    name : "John"
}
 

Вот где я был до сих пор :

 db.Things.aggregate([
    {
        $match:{
            _id:1
        }
    },
    {
        $lookup:{
            from:"Users",
            localField:"Users.userId",
            foreignField:"_id",
            as:"usersData"
        }
    },
    {
        $unwind : "$usersData"
    }
])
 

Заранее спасибо.

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

1. есть также userId : 00002 в _id = 1 , можете ли вы показать свой ожидаемый результат.

2. userId : 00002 у in _id = 1 нет роли creator » но spectator «в массиве «пользователи», поэтому он не является частью ожидаемого результата

3. это возможно, если есть 2 совпадающих использования из массива пользователей? если да, то как вы хотите получить результат, в отдельном документе или в том же документе.

4. Это невозможно. У каждого thing есть только один creator , и было бы идеально, если бы у меня было только имя создателя, _id но пока у меня есть name это нормально

Ответ №1:

  • $match вещи _id и role состояние пользователей
  • $unwind деконструировать users массив
  • $match users условие роли
  • $lookup с users коллекцией
  • $arrayElemAt чтобы получить первый элемент из результата поиска
  • $replaceRoot чтобы заменить указанный выше объект на корневой
 db.things.aggregate([
  { $match: { _id: 1, "users.role": "creator" } },
  { $unwind: "$users" },
  { $match: { "users.role": "creator" } },
  {
    $lookup: {
      from: "Users",
      localField: "users.userId",
      foreignField: "_id",
      as: "users"
    }
  },
  {
    $replaceRoot: {
      newRoot: { $arrayElemAt: ["$users", 0] }
    }
  }
])
 

Игровая площадка


Второй подход без использования $undind этапа,

  • $match вещи _id и role состояние пользователей
  • $filter для повторения цикла uses массива и фильтрации по role создателю
  • $arrayElemAt чтобы выбрать первый элемент из приведенного выше отфильтрованного результата
  • $lookup с users коллекцией
  • $arrayElemAt чтобы получить первый элемент из результата поиска
  • $replaceRoot чтобы заменить указанный выше объект на корневой
 db.things.aggregate([
  { $match: { _id: 1, "users.role": "creator" } },
  {
    $addFields: {
      users: {
        $arrayElemAt: [
          {
            $filter: {
              input: "$users",
              cond: { $eq: ["$this.role", "creator"] }
            }
          },
          0
        ]
      }
    }
  },
  {
    $lookup: {
      from: "Users",
      localField: "users.userId",
      foreignField: "_id",
      as: "users"
    }
  },
  {
    $replaceRoot: {
      newRoot: { $arrayElemAt: ["$users", 0] }
    }
  }
])
 

Игровая площадка