项目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_typepost_impressions_uniquevalue 属性,我们需要 运行 所有子文档的条件,以便将 name 属性 匹配到 post_story_adds_by_action_typepost_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' => 1name 等于 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.valuename 属性,其中 name 匹配 post_impressions_unique?反之,当 post_story_adds_by_action_type?

匹配时,如何检索子文档的 insignts.values.value.sharename 属性

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

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

感谢您的帮助。 谢谢。

你可以尝试这样的事情。

使用$$符号访问在$filter$map中迭代定义的变量。

$map用于trim显示insights数组中的valuesname的响应。

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