Значение массива коллекции проекта Mongo при условии

Я использую библиотеку Mongo php в службе, которая отвечает за хранение и извлечение некоторых социальных данных, в частности, из Facebook, и просто фрагмент, это выглядит примерно так: коллекция сообщений сообщений:

{
"_id":"5865aa8e9bbbe400010f97a2",
"insights":[
{
"name":"post_story_adds_unique",
"period":"lifetime",
"values":[
{
"value":10
}
]
},
{
"name":"post_story_adds",
"period":"lifetime",
"values":[
{
"value":11
}
]
},
{
"name":"post_story_adds_by_action_type_unique",
"period":"lifetime",
"values":[
{
"value":{
"like":10,
"comment":1
}
}
]
},
{
"name":"post_story_adds_by_action_type",
"period":"lifetime",
"values":[
{
"value":{
"like":10,
"comment":1
}
}
]
},
{
"name":"post_impressions_unique",
"period":"lifetime",
"values":[
{
"value":756
}
]
}
]
},
{

"_id":"586d939b9bbbe400010f9f12",
"insights":[
{
"name":"post_story_adds_unique",
"period":"lifetime",
"values":[
{
"value":76
}
]
},
{
"name":"post_story_adds",
"period":"lifetime",
"values":[
{
"value":85
}
]
},
{
"name":"post_story_adds_by_action_type_unique",
"period":"lifetime",
"values":[
{
"value":{
"like":73,
"comment":8,
"share":2
}
}
]
},
{
"name":"post_story_adds_by_action_type",
"period":"lifetime",
"values":[
{
"value":{
"like":74,
"comment":9,
"share":2
}
}
]
},
{
"name":"post_impressions_unique",
"period":"lifetime",
"values":[
{
"value":9162
}
]
}
]
}

Мы можем отметить, что все под-документы постов, то есть метрики, присутствуют в каждом посте, несомненно, с их соответствующими значениями.
Я считаю, что представленная выше структура данных не оптимальна для работы; если столкнуться с ситуацией, спроецировать пару значений этих поддокументов, скажем, post_story_adds_by_action_typeи post_impressions_unique«s value свойство, нам нужно выполнить условие для всех поддокументов, чтобы соответствовать name собственность на post_story_adds_by_action_type или же post_impressions_unique,

Я старался $elemMatch(projection), но, как говорится в документации, он возвращает только первый соответствующий элемент массива. Я смог сделать так:

$this->db->$collection->find([],
[
'projection' => [
'insights' => [
'$elemMatch' => [
'name' => 'post_impressions_unique'
]
],
'_id' => 0,
'insights.values.value' => 1,
],
]);

MongoDB\Driver\Cursor объект возвращается только с желаемым значением, установив это 'insights.values.value' => 1из поддокументов, которые имеют name равно post_impressions_unique,

Первое, о чем я подумал, это, конечно, использовать $or логический оператор:

$this->db->$collection->find([],
[
'projection' => [
'insights' => [
'$elemMatch' => [
'$or' => [
[
'name' => [
'$eq' => 'post_story_adds_by_action_type',
]
],
[
'name' => [
'$eq' => 'post_impressions_unique',
]
]
]

]
]
],
'_id' => 0,
'insights.name' => 1,
'insights.values.value.like' => 1,
'insights.values.value' => 1,
]);

Обратите внимание на прогнозы 'insights.values.value.share' => 1 'insights.values.value' => 1 в соответствии с позицией значения различных поддокументов.

Конечно, это не сработало, я получил массив post_impressions_unique только субдокументы; поэтому я должен был попробовать структуру агрегации https://docs.mongodb.com/manual/reference/operator/aggregation/filter/ :

$this->db->$name->aggregate(
[
[
'$project' => [
'insights' => [
'$filter' => [
'input' => '$insights',
'as' => 'name',
'cond' => [
'$or' => [
[
'$eq' => [
'name', '$post_story_adds_by_action_type',
]
],
[
'$eq' => [
'name', '$post_impressions_unique',
]
],
],
],
],
],
'_id' => 0,
'values.value.like' => 1,
'values.value' => 1,
],
]
]);

Это тоже не сработало, в этом случае я получил массив пустых insights объекты.

Я подумал об использовании Laravel-MongoDB пакет и воспользоваться преимуществами Eloquent строитель.

DB::collection($collection)->project(['insights' => ['$elemMatch' => ['name' => 'post_story_adds_unique']]])->get();

или же

DB::collection($collection)->project(['insights' => [
'$filter' => [
'input' => '$insights',
'as' => 'name',
'cond' => [
'name' => 'post_story_adds_unique',
]
]
],
'values.value.like' => 1
])->get();

Но все же я не мог получить значение в поддокументе. Я проверил Builder::project() функции, и кажется, что он также использует структуру агрегации, но я не смог выяснить соответствующий синтаксис для этого, если таковые имеются.

Мои вопросы следующие:

1- Как я могу получить определенные поддокументы? insights.values.value а также name свойства, где name Матчи post_impressions_unique? И наоборот, как получить поддокументы insignts.values.value.share а также name свойства, когда последний совпадает post_story_adds_by_action_type?

2- Какой правильный синтаксис использовать $filter в пределах $project(aggregation)?

Это в основном большая часть исследований, которые я проводил, и мне кажется, что я бегаю кругами.

Ценю твою помощь.
Спасибо.

1

Решение

Вы можете попробовать что-то вроде этого.

использование $$ запись для доступа к переменной, определенной в итерации в $filter а также $map,

$map используется для обрезки ответа на дисплей values а также name от insights массив.

   [
[
'$project' => [
'insights' => [
'$map' => [
'input' => [
'$filter' => [
'input' => '$insights',
'as' => 'insightf',
'cond' => [
'$or' => [
[
'$eq' => [
'$$insightf.name', 'post_story_adds_by_action_type',
]
],
[
'$eq' => [
'$$insightf.name', 'post_impressions_unique',
]
],
],
],
],
],
'as' => 'insightm',
'in' => [
'values' => '$$insightm.values.value',
'name' => '$$insightm.name',
],
],
],
'_id' => 0
],
]
];
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]