我在一个服务中使用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
&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
。
当然这没有用,我自己得到了一系列$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,
],
]
]);
个子文件;所以我不得不尝试聚合框架https://docs.mongodb.com/manual/reference/operator/aggregation/filter/:
insights
这也没有用,在这种情况下,我得到了一组空DB::collection($collection)->project(['insights' => ['$elemMatch' => ['name' => 'post_story_adds_unique']]])->get();
个对象。
我考虑使用laravel-mongodb包并利用Eloquent构建器。
DB::collection($collection)->project(['insights' => [
'$filter' => [
'input' => '$insights',
'as' => 'name',
'cond' => [
'name' => 'post_story_adds_unique',
]
]
],
'values.value.like' => 1
])->get();
或
Builder::project()
但我仍然无法获得子文档中的值。我检查了insights.values.value
函数,似乎它在内部也使用了聚合框架,但是我无法找到相应的语法(如果有的话)。
我的问题如下:
1-如何检索特定的子文档' name
和name
属性,post_impressions_unique
匹配insignts.values.value.share
?反之亦然,如何检索子文件' name
和post_story_adds_by_action_type
属性,后者匹配$filter
?
2-在$project(aggregation)
中使用n
的正确语法是什么?
这基本上是我一直在做的大部分研究,感觉好像我在圈子里跑。
感谢您的帮助。 谢谢。
答案 0 :(得分:2)
你可以尝试这样的事情。
使用$$
表示法访问$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
],
]
];