使用聚合函数查找数组中对象的索引

4

有没有办法在聚合管道中获取索引,我有一个长时间的聚合查询结果

[
    {
        "_id": "59ed949227ec482044b2671e",
        "points": 300,
        "fan_detail": [
            {
                "_id": "59ed949227ec482044b2671e",
                "name": "mila   ",
                "email": "mila@gmail.com ",
                "password": "$2a$10$J0.KfwVnZkaimxj/BiqGW.D40qXhvrDA952VV8x.xdefjNADaxnSW",
                "username": "mila  0321",
                "updated_at": "2017-10-23T07:04:50.004Z",
                "created_at": "2017-10-23T07:04:50.004Z",
                "celebrity_request_status": 0,
                "push_notification": [],
                "fan_array": [],
                "fanLength": 0,
                "celeb_bio": null,
                "is_admin": 0,
                "is_blocked": 2,
                "notification_setting": [
                    1,
                    2,
                    3,
                    4,
                    5,
                    6,
                    7
                ],
                "total_stars": 0,
                "total_points": 134800,
                "user_type": 2,
                "poster_pic": null,
                "profile_pic": "1508742289662.jpg",
                "facebook_id": "alistnvU79vcc81PLW9o",
                "is_user_active": 1,
                "is_username_selected": "false",
                "__v": 0
            }
        ]
    }
],

我想在聚合查询中找到_id的索引,而且上面的数组中可能包含数百个对象。

1个回答

6

根据您拥有的MongoDB版本,有不同的方法:

$indexOfArray - MongoDB 3.4

对于这个最好的运算符是 $indexOfArray,如果您有它可用的话。名称已经说明了一切:

Model.aggregate([
  { "$match": { "fan_detail._id": mongoose.Types.ObjectId("59ed949227ec482044b2671e") } },

  { "$addFields": { 
    "fanIndex": {
      "$indexOfArray": [
        "$fan_detail._id",
        mongoose.Types.ObjectId("59ed949227ec482044b2671e")
      ]
    }
  }}
])

$unwindincludeArrayIndex - MongoDB 3.2

在MongoDB 3.2中,通过使用$unwind语法,您可以从数组中获取索引。但是这需要您对数组进行$unwind操作:

Model.aggregate([
  { "$match": { "fan_detail._id": mongoose.Types.ObjectId("59ed949227ec482044b2671e") } },
  { "$unwind": { "path": "$fan_detail", "includeArrayIndex": true } },
  { "$match": { "fan_detail._id": mongoose.Types.ObjectId("59ed949227ec482044b2671e") } }
])

mapReduce - 早期版本

在MongoDB 3.2之前的早期版本中,聚合管道无法返回数组索引。因此,如果您想要匹配的索引而不是所有数据,则需要使用mapReduce

Model.mapReduce({
  map: function() {
    emit(
      this._id,
      this['fan_detail']
        .map( f => f._id.valueOf() )
        .indexOf("59ed949227ec482044b2671e") 
    )
  },
  reduce: function() {},
  query: { "fan_detail._id": mongoose.Types.ObjectId("59ed949227ec482044b2671e") }
})

在所有情况下,我们基本上会“查询”数组中是否“某处”存在该元素。如果未找到,则“indexOf”变体将返回-1
另外,$addFields 只是一个示例。如果你真正想要不返回数百个项目的数组,那么你可能会使用 $project 或其他输出方式。

谢谢你的回答,它是正确的。是的,我也在使用分页来限制100条记录。 - Irfan Khan
@IrfanKhan 如果你只是想简单地做到这一点,还有$slice。"数组分页"是为什么它自MongoDB的早期版本以来就存在了。 - Neil Lunn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接