项目Mongo 某个条件下的集合数组值
Project Mongo collection array value under a condition
我在一项服务中使用 Mongo php 库,该服务负责存储和检索一些社交数据,特别是来自 Facebook 的,只是一个片段,它是这样的,一个post 的见解集合:
{
"_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 的子文档,即指标,都存在于每个 post 中,当然,它们具有相应的值。
我相信上面介绍的数据结构并不是最适合使用的;如果面临投影几个子文档值的情况,比如 post_story_adds_by_action_type
和 post_impressions_unique
的 value
属性,我们需要 运行 所有子文档的条件,以便将 name
属性 匹配到 post_story_adds_by_action_type
或 post_impressions_unique
.
我试过 $elemMatch(projection)
,但正如文档所说,它只是 returns 第一个匹配的数组元素。我能够这样做:
$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,
]);
Note the projections 'insights.values.value.share' => 1
'insights.values.value' => 1
corresponding to the different sub-documents value position.
当然这不行,我单独得到了一个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
?反之,当 post_story_adds_by_action_type
?
匹配时,如何检索子文档的 insignts.values.value.share
和 name
属性
2- 在 $project(aggregation)
中使用 $filter
的正确语法是什么?
这基本上是我一直在做的大部分研究,感觉好像我在运行兜圈子。
感谢您的帮助。
谢谢。
你可以尝试这样的事情。
使用$$
符号访问在$filter
和$map
中迭代定义的变量。
$map
用于trim显示insights
数组中的values
和name
的响应。
[
[
'$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
],
]
];
我在一项服务中使用 Mongo php 库,该服务负责存储和检索一些社交数据,特别是来自 Facebook 的,只是一个片段,它是这样的,一个post 的见解集合:
{
"_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 的子文档,即指标,都存在于每个 post 中,当然,它们具有相应的值。
我相信上面介绍的数据结构并不是最适合使用的;如果面临投影几个子文档值的情况,比如 post_story_adds_by_action_type
和 post_impressions_unique
的 value
属性,我们需要 运行 所有子文档的条件,以便将 name
属性 匹配到 post_story_adds_by_action_type
或 post_impressions_unique
.
我试过 $elemMatch(projection)
,但正如文档所说,它只是 returns 第一个匹配的数组元素。我能够这样做:
$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,
]);
Note the projections
'insights.values.value.share' => 1
'insights.values.value' => 1
corresponding to the different sub-documents value position.
当然这不行,我单独得到了一个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
?反之,当 post_story_adds_by_action_type
?
insignts.values.value.share
和 name
属性
2- 在 $project(aggregation)
中使用 $filter
的正确语法是什么?
这基本上是我一直在做的大部分研究,感觉好像我在运行兜圈子。
感谢您的帮助。 谢谢。
你可以尝试这样的事情。
使用$$
符号访问在$filter
和$map
中迭代定义的变量。
$map
用于trim显示insights
数组中的values
和name
的响应。
[
[
'$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
],
]
];