MongoDB Агрегационный конвейер, обновить существующие элементы в массиве после разделения строки - PullRequest
1 голос
/ 02 апреля 2020

Пример Do c:

{
  bioupdate: [
    {
      date: "02/03/2020",
      ts: "1583133621197-02/03/2020_15:20:21",
      status: "1"
    },
    {
      date: "02/03/2020",
      ts: "1583135570542-02/03/2020_15:52:50",
      status: "1"
    },
    {
      date: "02/03/2020",
      ts: "1583135586272-02/03/2020_15:53:06",
      status: "0"
    },
    {
      date: "21-03-2020:17:35:08",
      ts: 1584783308231,
      status: "1"
    }
  ]
}

Ниже приведен код, который я пробовал с конвейером агрегации, разбивая строку с первым '-' и беря первый элемент, который отметка времени эпохи и сохранение ее в том же поле в существующем массиве.

db.novelmodel.aggregate([
  {$match: {pin: "JAIN"}},
  {
    $project: {
    pin: 1,
     bioupdate: {
      $filter: {
         input: "$bioupdate",
         as: "bioupdateArray",

         cond: { $and: [
          {$arrayElemAt:[{$split:["$$bioupdateArray.ts", "-"]}, 0]}
           ] }
      }
   }
  }
},

  {$out:"novelmodel"}
]);

Появляется сообщение об ошибке: "errmsg" : "$split requires an expression that evaluates to a string as a first argument, found: double". Я не уверен, как фильтр принимает только дату с разделителем ' - 'в строке

1 Ответ

1 голос
/ 02 апреля 2020

Ваш вопрос должен быть последним документом, в котором ts имеет тип NumberLong() вместо строки, что и вызывает ошибку. Попробуйте выполнить запрос ниже:

db.collection.aggregate([
  /** Re-create 'bioupdate' with updated data */
  {
    $addFields: {
      bioupdate: {
        $map: {
          input: "$bioupdate", // Iterate on 'bioupdate' array
          in: {
            $cond: [
              { $eq: [{ $type: "$$this.ts" }, "string"] }, // Check if 'ts' field in current object is of type string
              /** If YES, Split it & get first element from array, it will be string if you want to keep is as number convert using '$long' */
              {
                $mergeObjects: [
                  "$$this",
                  {
                    ts: {
                      $toLong: {
                        $arrayElemAt: [{ $split: ["$$this.ts", "-"] }, 0]
                      }
                    }
                  }
                ]
              },
              /** If NO, Just to make sure convert existing to long & merge with actual object & push entire object back to array */
              { $mergeObjects: ["$$this", { ts: { $toLong: "$$this.ts" } }] }
            ]
          }
        }
      }
    }
  }
]);

Тест: MongoDB-Playground

...