MongoDB условный поиск с родительским документом и вложенными документами в массиве - PullRequest
0 голосов
/ 07 ноября 2019

Допустим, у меня есть "схема" mongodb, подобная этой:

offers: Schema = {
      name: String,
      validityStart: Date,
      validityEnd: Date,
      customized: [
         {
            validityStart: Date,
            validityEnd: Date,
            user: String
         }
     ]
}

По словам: здесь у нас есть коллекция предложений, действительных между датами, указанными validityStart и validityEnd. Каждое предложение имеет подмассив, который определяет, что пользователь может иметь это предложение "настроенным", то есть иметь более длительное время использования.

Я могу запросить все предложения, доступные с

Offer.find({ $and: [{ validityStart: { $lte: today } }, { validityEnd: { $gte: today } }] })

, но если указано « user », мне нужно создать запрос, который покажет мне все предложения и покажет «настроенные» предложения путем фильтрации через поле пользователя.

Вот пример того, чего я хочу достичь: представьте, что у вас есть несколько предложений на декабрь

[
    {
      name: "Soccer Game 2020",
      validityStart: "2019-12-1",
      validityEnd: "2019-12-31"
    },
    {
      name: "Golf Equipment",
      validityStart: "2019-12-1",
      validityEnd: "2019-12-31"
    }
]

, но я позволю пользователю FOO быть ранней пташкой на 1 месяц для футбольной игры, у меня будет:

[
    {
      name: "Soccer Game 2020",
      validityStart: "2019-12-1",
      validityEnd: "2019-12-31",
      customized:[
        {
           validityStart: "2019-11-1",
           validityEnd: "2019-11-30",
           user: "FOO"
        }
      ]
    },
    ---
]

Как вернуть для всех пользователей «родительские» даты, но для некоторых пользователей, указанных в настраиваемом массиве, их соответствующие даты? Например:

[
    {
      name: "Soccer Game 2020",
      validityStart: "2019-11-1",
      validityEnd: "2019-11-30"
    },
    {
      name: "Golf Equipment",
      validityStart: "2019-12-1",
      validityEnd: "2019-12-31"
    }
]

Я не знаю, как создать такой запрос.

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

1 Ответ

1 голос
/ 08 ноября 2019

Это оказалось немного более многословным, чем мне хотелось бы найти решение, но оно выполнило свою работу. Кроме того, предлагается только хранить даты как date объекты в документах, если они в настоящее время являются строками.

Запрос:

db.collection.aggregate([
  {
    $addFields: {
      userCustomOffer: {
        $filter: {
          input: "$customized",
          as: "elem",
          cond: {
            $eq: ["$$elem.user", "FOO"]
          }
        }
      }
    }
  },
  {
    $project: {
      name: 1,
      validityStart: {
        $cond: {
          if: {
            $or: [
              {
                $eq: ["$userCustomOffer", []]
              },
              {
                $eq: ["$userCustomOffer", null]
              }
            ]
          },
          then: "$validityStart",
          else: {
            $arrayElemAt: ["$userCustomOffer.validityStart", 0]
          }
        }
      },
      validityEnd: {
        $cond: {
          if: {
            $or: [
              {
                $eq: ["$userCustomOffer", []]
              },
              {
                $eq: ["$userCustomOffer", null]
              }
            ]
          },
          then: "$validityEnd",
          else: {
            $arrayElemAt: ["$userCustomOffer.validityEnd", 0]
          }
        }
      }
    }
  }
]);

Образцы документов взяты в качестве варианта использования:

[
  {
    name: "Soccer Game 2020",
    validityStart: "2019-12-1",
    validityEnd: "2019-12-31",
    customized: [
      {
        validityStart: "2019-11-1",
        validityEnd: "2019-11-30",
        user: "FOO"
      },
      {
        validityStart: "2019-10-1",
        validityEnd: "2019-10-31",
        user: "BAZ"
      }
    ]
  },
  {
    name: "Golf Equipment",
    validityStart: "2019-12-1",
    validityEnd: "2019-12-31",
    customized: [
      {
        validityStart: "2019-11-1",
        validityEnd: "2019-11-30",
        user: "BAR"
      }
    ]
  },
  {
    name: "Hockey Kit",
    validityStart: "2019-01-1",
    validityEnd: "2019-02-28"
  }
]

Результаты запроса:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "name": "Soccer Game 2020",
    "validityEnd": "2019-11-30",
    "validityStart": "2019-11-1"
  },
  {
    "_id": ObjectId("5a934e000102030405000001"),
    "name": "Golf Equipment",
    "validityEnd": "2019-12-31",
    "validityStart": "2019-12-1"
  },
  {
    "_id": ObjectId("5a934e000102030405000002"),
    "name": "Hockey Kit",
    "validityEnd": "2019-02-28",
    "validityStart": "2019-01-1"
  }
]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...