Как я могу использовать существующее поле в качестве модификатора $ match внутри моего запроса агрегации Mon go - PullRequest
0 голосов
/ 25 февраля 2020

Моя структура данных похожа на:

{
  _id: ObjectId("5a7f534b337e8d2b97ff2ff"),
  cutoff: 3,
  schedules: [
    {
      starts: ISODate('2020-04-22T00:00:00.000Z'),
      ends: ISODate('2020-04-22T00:00:00.000Z'),
      repeats: 'never'
    },
    {
      starts: ISODate('2020-04-30T00:00:00.000Z'),
      ends: ISODate('2020-06-30T00:00:00.000Z'),
      repeats: 'monthly'
    }
  ]
}

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

  const from = new Date(2020, 04, 25)
  const to = new Date(2020, 05, 5)

  await datastore
    .collection('things')
    .aggregate([
      {
        $match: {
          'schedules.starts': { $lte: to },
          'schedules.ends': { $gte: from }
        }
      }
    ])

Проблема заключается в том, что я Мне нужно учесть срез в поиске, поэтому я обнаружил $expr и попытался применить его к своему запросу:

$match: {
  'schedules.starts': { $lte: to.toDate() },
  'schedules.ends': { $expr: { $gte: { $add: [ from.toDate(), { $multiply: [ '$cutoff', 24, 60, 60000 ] } } } }
}

Я не пытался закончить эксперимент с $expr, чтобы получить его работать в запросе, но я либо получаю сообщение об ошибке, что он используется неправильно, либо я не получаю никаких результатов. Я не уверен, что делать дальше.

Я рассмотрел вопрос об использовании $project или $addFields перед совпадением, чтобы упростить его, но из руководства я понимаю, что это приведет к остановке моих многоключевых индексов. работает.

1 Ответ

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

Ваше $match состояние не совсем понятно для меня. В общем случае вы можете использовать существующие поля:

var from = new Date(2020, 04, 25)
var to = new Date(2020, 05, 5)

db.collection.aggregate([
   { $addFields: { from: from } },
   { $addFields: { to: to } },
   { $addFields: { ends: { $toDate: { $add: [from.getTime(), { $multiply: ['$cutoff', 24, 60, 60, 1000] }] } } } }
])

возвращает

{ 
    "_id" : ObjectId("5e5530e922139e9b31aa786c"), 
    "cutoff" : 3.0, 
    "schedules" : [
        {
            "starts" : ISODate("2020-04-22T02:00:00.000+0200"), 
            "ends" : ISODate("2020-04-22T02:00:00.000+0200"), 
            "repeats" : "never"
        }, 
        {
            "starts" : ISODate("2020-04-30T02:00:00.000+0200"), 
            "ends" : ISODate("2020-06-30T02:00:00.000+0200"), 
            "repeats" : "monthly"
        }
    ], 
    "from" : ISODate("2020-05-25T00:00:00.000+0200"), 
    "to" : ISODate("2020-06-05T00:00:00.000+0200"), 
    "ends" : ISODate("2020-05-28T00:00:00.000+0200")
}

Для использования в $match это будет

db.collection.aggregate([
   {
      $match: {
         $expr: {
            $gte: [
               "$schedules.ends",
               { $toDate: { $add: [from.getTime(), { $multiply: ['$cutoff', 24, 60, 60, 1000] }] } }
            ]
         }
      }
   }
])
...