Как избежать временных разрывов при агрегации OHLC в mongoDB

1

Я пытаюсь извлечь ohlc 5-минутный интервал из 1-минутного интервала DB, хранящегося в mongoDB. Ниже мой текущий запрос.

    myModel.aggregate([
    {"$project":
      {
        "data":
        {
          "$let":
          {
            "vars":
            {
              "mints":{"$arrayElemAt":[{"$arrayElemAt":["$data",0]},0]},
              "maxts":{"$arrayElemAt":[{"$arrayElemAt":["$data",-1]},0]}
            },
            "in":
            {
              "$map":
              {
                "input":{"$range":["$$mints",{"$add":["$$maxts",300]},300]},
                "as":"rge",
                "in":
                {
                  "$let":
                  {
                    "vars":
                    {
                      "five":
                      {
                        "$filter":
                        {
                          "input":"$data",
                          "as":"fres",
                          "cond":
                          {
                            "$and":
                            [
                              {"$gte":[{"$arrayElemAt":["$$fres",0]},"$$rge"]},
                              {"$lt":[{"$arrayElemAt":["$$fres",0]},{"$add":["$$rge",300]}]}
                            ]
                          }
                        }
                      }
                    },
                    "in":
                    [
                      {"$arrayElemAt":[{"$arrayElemAt":["$$five",-1]},0]},
                      {"$arrayElemAt":[{"$arrayElemAt":["$$five",0]},1]},
                      {"$max":{"$map":{"input":"$$five","as":"res","in":{"$arrayElemAt":["$$res",2]}}}},
                      {"$min":{"$map":{"input":"$$five","as":"res","in":{"$arrayElemAt":["$$res",3]}}}},
                      {"$arrayElemAt":[{"$arrayElemAt":["$$five",-1]},-2]},
                      {"$arrayElemAt":[{"$arrayElemAt":["$$five",-1]},-1]}
                    ]
                  }
                }
              }
            }
          }
        }
      }
    }
  ]);

Кажется, он извлекает 5 минут, но не заботится о пробелах за 1-минутный интервал данных. Вместо этого для тех моментов времени я получаю нулевой массив. Как нам избежать нулевых массивов?

Пример 1 Данные БД: https://gist.github.com/parthi2929/36e6898cff7be45ccdd008ec750e70e9

5 минут извлеченного моментального снимка здесь

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

Я попытался вставить { "$ne":[{"$arrayElemAt":["$$fres",0]},null] } в $ и операторе, но это не помогло.

Обновление 14 февраля 2018 года: согласно предложению Veeram ниже приведен модифицированный код, включенный в предлагаемые изменения. Тем не менее, я все еще получаю один пустой массив (это, по-видимому, много пустых массивов, в этот промежуток времени теперь нет, но заменен одним пустым массивом), который также должен быть исправлен.

db.getCollection('ohlc-koinex-1').aggregate(
[
    {"$project":
      {
        "data":
        {
          "$let":
          {
            "vars":
            {
              "mints":{"$arrayElemAt":[{"$arrayElemAt":["$data",0]},0]},
              "maxts":{"$arrayElemAt":[{"$arrayElemAt":["$data",-1]},0]}
            },
            "in":
            {
                "$setDifference":
                [
                    {
                      "$map":
                      {
                        "input":{"$range":["$$mints",{"$add":["$$maxts",300]},300]},
                        "as":"rge",
                        "in":
                        {
                          "$let":
                          {
                            "vars":
                            {
                              "five":
                              {
                                "$filter":
                                {
                                  "input":"$data",
                                  "as":"fres",
                                  "cond":
                                  {
                                    "$and":
                                    [
                                      {"$gte":[{"$arrayElemAt":["$$fres",0]},"$$rge"]},
                                      {"$lt":[{"$arrayElemAt":["$$fres",0]},{"$add":["$$rge",300]}]}
                                    ]
                                  }
                                }
                              }
                            },
                            "in":
                            {
                                "$cond":[
                                    {"$eq":["$$five",[]]},
                                    "$$five",
                                    [
                                      {"$arrayElemAt": [{"$arrayElemAt":["$$five",-1]},0]},
                                      {"$arrayElemAt":[{"$arrayElemAt":["$$five",0]},1]},
                                      {"$max":{"$map":{"input":"$$five","as":"res","in":{"$arrayElemAt":["$$res",2]}}}},
                                      {"$min":{"$map":{"input":"$$five","as":"res","in":{"$arrayElemAt":["$$res",3]}}}},
                                      {"$arrayElemAt":[{"$arrayElemAt":["$$five",-1]},-2]},
                                      {"$arrayElemAt":[{"$arrayElemAt":["$$five",-1]},-1]}
                                    ]
                                ]
                             }
                          }
                        }
                      }
                  },[]
                 ]
            }
          }
        }
      }
    }
]
)

Вот снимок результата

Теги:
mongoose

1 ответ

1

Вы можете добавить $cond operator для учета пробелов, за которыми следует $filter чтобы отфильтровать значения пустых массивов.

Вам потребуются два изменения.

Первое изменение для хранения значений [] для пробелов вместо массива с нулевыми значениями.

Обновите внутреннее выражение $ let ниже:

{
  "$let":{
    "vars":{"five":...},
    "in":{
      "$cond":[
        {"$eq":["$$five",[]]},
        "$$five",
        [{"$arrayElemAt":[{"$arrayElemAt":["$$five",-1]},0]},
         ....
        {"$arrayElemAt":[{"$arrayElemAt":["$$five",-1]},-1]}]
      ]
    }
  }
}

Второе изменение для фильтрации пустых значений массива на выходе.

{
  "$project":{
    "data":{
      "$let":{
        "vars":{"mints":...},
        "in":{"$filter":{"input":{"$map":...},as:"flr", "cond":{"$ne":["$$flr",[]]}}}
      }
    }
  }
}
  • 0
    Большое спасибо, Верам. Однако незначительная проблема. Все пустые массивы между пропусками исчезли, но теперь заменены одним пустым массивом, как я показал в обновленном вопросе выше. Можете ли вы проверить?
  • 0
    Yw. Обновленный ответ для замены setDifference на $ filter. Должен работать как ожидалось.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню