#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'
]
]
]