如何在使用MongoDB聚合框架展开数组后投影数组索引

时间:2014-12-27 01:07:00

标签: mongodb aggregation-framework

使用MongoDB聚合管道展开数组(http://docs.mongodb.org/manual/reference/operator/aggregation/unwind/#pipe._S_unwind)时是否可以访问数组索引?

例如,假设我在集合“c”中展开此文档:

{_id: 1, elements: ["a", "b", "c"]}

然后这个操作:

db.c.aggregate([
 {$unwind: "$elements"}
])

将返回文档的光标:

[
 {_id: 1, elements: "a"},
 {_id: 1, elements: "b"},
 {_id: 1, elements: "c"}
]

我希望能够在解开之前弄清楚“a”有索引0,“b”有索引1而“c”在原始数组中有索引“2”。

如何在展开操作中投影数组索引?

2 个答案:

答案 0 :(得分:10)

新发布的MongoDB 3.2支持展开数组索引。

您可以传递一个包含字段 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@+id/filterbutton" android:layout_alignParentTop="true" android:fadingEdge="none" android:fillViewport="true" android:isScrollContainer="true" android:scrollbars="none"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:id="@+id/linearLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:layout_gravity="top" android:background="#FFFFFF" android:orientation="horizontal"> <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/gen" /> <TextView android:id="@+id/gen" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text=" Search" android:textSize="25sp" android:textStyle="bold" /> </LinearLayout> <LinearLayout android:id="@+id/linearLayout2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/linearLayout1" android:layout_marginTop="53dp" android:background="#FFFFFF" android:orientation="horizontal"> <ImageView android:id="@+id/imageView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/year" /> <TextView android:id="@+id/movieyear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text=" Search By Year" android:textSize="25sp" android:textStyle="bold" /> </LinearLayout> <LinearLayout android:id="@+id/linearLayout3" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_below="@+id/linearLayout2" android:layout_marginTop="53dp" android:background="#FFFFFF" android:orientation="horizontal"> <ImageView android:id="@+id/imageView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/im" /> <TextView android:id="@+id/imdb_rating" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text=" Search" android:textSize="25sp" android:textStyle="bold" /> </LinearLayout> <LinearLayout android:id="@+id/linearLayout4" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/linearLayout3" android:layout_marginTop="53dp" android:background="#FFFFFF" android:orientation="horizontal"> <ImageView android:id="@+id/imageView4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/rt2" /> <TextView android:id="@+id/rotten_rating" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text=" Search By Rating" android:textSize="24sp" android:textStyle="bold" /> </LinearLayout> </LinearLayout> </ScrollView> <Button android:id="@+id/filterbutton" android:layout_width="match_parent" android:layout_height="58dp" android:layout_alignParentBottom="true" android:background="#ffff9a88" android:text="filter" android:textStyle="bold" /> </RelativeLayout> 的字段和包含数组索引的字段$unwind,而不是传递path运算符的路径。

来自MongoDB official documentation

includeArrayIndex

答案 1 :(得分:4)

目前,使用聚合框架似乎无法做到这一点。有一个尚未解决的未决问题:https://jira.mongodb.org/browse/SERVER-4588

作为一种解决方法,您可以使用Map-reduce,map函数为每个数组元素分配索引。

var map = function(){
    for(var i=0;i<this.elements.length;i++){
    emit({"_id":this._id,"index":i},{"index":i,"value":this.elements[i]});
    }
}