在条件

时间:2017-02-07 02:20:10

标签: php mongodb aggregation-framework projection

我在一个服务中使用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_typepost_impressions_uniquevalue 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-如何检索特定的子文档' namename属性,post_impressions_unique匹配insignts.values.value.share?反之亦然,如何检索子文件' namepost_story_adds_by_action_type属性,后者匹配$filter

2-在$project(aggregation)中使用n的正确语法是什么?

这基本上是我一直在做的大部分研究,感觉好像我在圈子里跑。

感谢您的帮助。 谢谢。

1 个答案:

答案 0 :(得分:2)

你可以尝试这样的事情。

使用$$表示法访问$filter$map中迭代中定义的变量。

$map用于修改从values数组中显示nameinsights的响应。

   [
      [
      '$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
        ],
      ]
    ];