Требуется агрегированная справка MongoDB

#php #mongodb #aggregation-framework

#php #mongodb #агрегация-фреймворк

Вопрос:

Может быть, кто-нибудь может мне помочь. У меня есть несколько записей изображений в моем MongoDB. Я хочу запросить и обновить структуру возвращаемых данных. Поэтому я использую агрегацию MongoDB в PHP.

Мои записи выглядят так:

 [
{
  "_id":{"$oid":"5fbe7d29300f22765c25b741"},
  "name":"192.168.1.64_01_20200708121713085_TIMING.jpg",
  "created":1602600596,
  "images":[
    {
      "name":"thumb_192.168.1.64_01_20200708121713085_TIMING.jpg",
      "type":"thumb",      
      "url":"https://firebasestorage.googleapis.com...",
      "size":12150
    },
    {
      "name":"resized_192.168.1.64_01_20200708121713085_TIMING.jpg",
      "type":"resized",
      "url":"https://firebasestorage.googleapis.com...",
      "size":136873
    }, 
    {
      "name":"192.168.1.64_01_20200708121713085_TIMING.jpg",
      "type":"original",
      "url":"https://firebasestorage.googleapis.com...",
      "size":2149262
    }
  ]
}, 
{
...
}
]
 

Я хочу преобразовать массив изображений в объект с ключами и удалить некоторые дополнительные данные из массива и добавить читаемую временную метку.
Итак, ожидаемый результат запроса должен быть:

 [
{
  "name":"192.168.1.64_01_20200708121713085_TIMING.jpg",
  "created":1602600596,
  "createdString": "2020-12-16 15:11:06",
  "images":{
    "thumb": {
      "name":"thumb_192.168.1.64_01_20200708121713085_TIMING.jpg",
      "url":"https://firebasestorage.googleapis.com..."
    },
    "resized": {
      "name":"resized_192.168.1.64_01_20200708121713085_TIMING.jpg",
      "url":"https://firebasestorage.googleapis.com..."
    }
  }
}, 
{
  "name":"192.168.1.64_01_20200708131711001_TIMING.jpg",
  "created":1602601234,
  ....
}
]
 

Это моя агрегационная функция в PHP:

 $pipeline = [   
                [
                    '$match' => [
                        'created' => [
                            '$gte' => mktime(0,0,0,8,1,2020),
                            '$lt' => mktime(0,0,0,10,2,2020)
                         ]
                    ],
                ],              
                [
                    '$sort' => [
                        'created' => 1
                    ]               
                ],
                [
                    '$group' => [
                        '_id' => null,
                        'data' => [ '$push' => '$$ROOT' ],
                    ],
                ],
                [   // get every 10th images of all data
                    '$project' => [
                        'created' => '$created',
                        'allData' => [
                                '$map' => [
                                    'input' => [ 
                                        '$range' => [ 
                                            0, 
                                            [ '$size' => '$data' ], 
                                            10
                                        ] 
                                    ],    
                                'as' => 'index',
                                'in' => [ '$arrayElemAt' => [ '$data', '$$index' ] ]
                            ]
                        ]
                    ]               
                ],  
                [   // remove props
                    '$unset' => [
                        'allData._id',
                        'allData.images.size',
                        'allData.images.path',
                    ]                           
                ],

                [   // filter only thumb and resized images from input --> not working
                    '$project' => [
                        'created' => '$created',
                        'allData' => '$allData',
                        'data' => [
                            '$filter' => [
                                'input' => '$allData.images' , 
                                'as' => 'item', 
                                'cond' => [
                                    '$or' => [
                                        [
                                            '$eq' => [
                                              '$$item.type', 'thumb'
                                            ]
                                        ],
                                        [
                                            '$eq' => [
                                              '$$item.type', 'resized'
                                            ]
                                        ]
                                    ]
                                ]
                            ]
                        ]
                    ]
                ],
                [   // make array of objects with type as key
                    '$project' => [
                        'created' => '$created',
                        'createdString' => [
                            '$dateToString' => [
                              'format' => '%Y-%m-%d %H:%M:%S', 
                              'date' => [
                                '$toDate' => [
                                  '$multiply' => [
                                    1000, '$created'
                                  ]
                                ]
                              ]
                            ]   
                          ],
                        'images' => [
                            '$arrayToObject' => [
                              '$zip' => [
                                'inputs' => [
                                 '$images.type', '$images'
                                ]
                              ]
                            ]
                        ],                                
                    ]
                ]                               
            ];  

$aggregate = new MongoDBDriverCommand([
                'aggregate' => $collection,
                'cursor' => new stdClass,
                'pipeline' => $pipeline
            ]
        );
$manager = new MongoDBDriverManager();
$result = $manager->executeCommand('images', $aggregate);
 

Мой конвейер будет работать до тех пор, пока не будут удалены некоторые ключи из массива, но я не могу заставить его работать для преобразования массива в объектный диалог…

Было бы здорово, если бы кто-нибудь мог мне помочь. Большое вам спасибо.

Ответ №1:

Ну, я просто сосредоточусь на части преобразования массива в объект

вот JS-код для этого,

 db.collection.aggregate([
  {
    $project: {
      name: 1,
      created: 1,
      images: {
        $map: {
          input: "$images",
          as: "image",
          in: {
            $mergeObjects: [
              {
                k: "$$image.type",
                v: {
                  name: "$$image.name",
                  url: "$$image.url"
                }
              }
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      name: 1,
      created: 1,
      images: {
        $arrayToObject: "$images"
      }
    }
  }
])
 

Вам нужно будет преобразовать объекты в ассоциативные массивы. Для простоты, вот как выглядит преобразованная часть ‘createdString’ на заключительном этапе проекта,

 createdString: {
        "$dateToString": {
          "format": "%Y-%m-%d %H:%M:%S",
          "date": {
            "$toDate": {
              "$multiply": [
                1000,
                "$created"
              ]
            }
          }
        }
      }
 

Надеюсь, это поможет.
Возможно, один из разработчиков PHP может помочь вам с преобразованием этого.

Наконец, это типичный результат, который вы должны получить с помощью этой агрегации,

 [
  {
    "_id": ObjectId("5fbe7d29300f22765c25b741"),
    "created": 1.602600596e 09,
    "images": {
      "original": {
        "name": "192.168.1.64_01_20200708121713085_TIMING.jpg",
        "url": "https://firebasestorage.googleapis.com..."
      },
      "resized": {
        "name": "resized_192.168.1.64_01_20200708121713085_TIMING.jpg",
        "url": "https://firebasestorage.googleapis.com..."
      },
      "thumb": {
        "name": "thumb_192.168.1.64_01_20200708121713085_TIMING.jpg",
        "url": "https://firebasestorage.googleapis.com..."
      }
    },
    "name": "192.168.1.64_01_20200708121713085_TIMING.jpg"
  }
]
 

вот моя попытка преобразовать его в PHP,

                     [  
                    '$project' => [
                        'name' => 1,
                        'created' => 1,
                        'images' => [
                                '$map' => ['input' => '$images'],    
                                'as' => 'index',
                                'in' => [ 
                                    '$mergeObjects' => [ 
                                        [
                                            'k' => '$$image.type',
                                            'v' => [
                                                'name'=> '$$image.name',
                                                'url'=> '$$image.url'
                                            ]
                                        ]
                                    ] 
                                ]
                            ]
                        ]
                    ] ,
                    [  
                        '$project' => [
                            'name' => 1,
                            'created' => 1,
                            'images' => [
                                '$arrayToObject': '$images'
                            ]
                        ]
                    ]