Golang在json响应中获取数组索引值

时间:2016-03-10 14:35:04

标签: arrays json mongodb sorting go

所以我对数据库(mongodb)有一些查询,它将按值字段排序结果。

all := EValues{}
err := con.Find(bson.M{"name": "somename}).Sort("-value").All(&all)

Json输出如下:

 "values": [
    {
      "user_name": "guest7485",
      "value": 8911,
      "value_date": "2016-03-09T14:40:34.512Z"
    },
    {
      "user_name": "guest7485",
      "value": 539,
      "value_date": "2016-03-07T14:11:05.217Z"
    },
    {
      "user_name": "guest7485",
      "value": 221,
      "value_date": "2016-03-07T14:11:08.853Z"
    },
    {
      "user_name": "guest7485",
      "value": 77,
      "value_date": "2016-03-07T14:11:12.377Z"
    }
  ]

在我的json响应中,我需要添加参数" position"对于所有结果,它应该基本上等于1 - 第一结果,2秒结果等等。所以我的最终输出应该是:

 "values": [
    {
      "position": 1,
      "user_name": "guest7485",
      "value": 8911,
      "value_date": "2016-03-09T14:40:34.512Z"
    },
    {
      "position": 2,
      "user_name": "guest7485",
      "value": 539,
      "value_date": "2016-03-07T14:11:05.217Z"
    },
    {
      "position": 3,
      "user_name": "guest7485",
      "value": 221,
      "value_date": "2016-03-07T14:11:08.853Z"
    },
    {
      "position": 4,
      "user_name": "guest7485",
      "value": 77,
      "value_date": "2016-03-07T14:11:12.377Z"
    }
  ]

我想知道如何用mgo来解决这个问题并且总的来说,如果有人能给我最有效的方法来解决这个问题,我会非常感激。

更新

Evalues的定义如下:

type EValue struct {
    ID bson.ObjectId `json:"-" bson:"_id,omitempty"`
    Name string             `json:"-" bson:"name"`
    UserId    bson.ObjectId `json:"-" bson:"userId"`
    UserName  string        `json:"user_name" bson:"userName"`
    Value     int64         `json:"value" bson:"value"`
    AddedTime time.Time     `json:"value_date" bson:"addedTime"`
}

type EValues []EValue

2 个答案:

答案 0 :(得分:0)

向EValue添加位置字段:

type EValue struct {
    ... other fields here
    Position int `json:"position" bson:"-"`
}

循环遍历db结果并设置字段:

for i := range all {
    all[i].Position = i + 1
}

将结果标记为JSON。

答案 1 :(得分:0)

使用MongDB 3.2,可以使用 $unwind 运算符完成此操作,您可以在其中传递包含字段path的对象和将保留的字段includeArrayIndex数组索引:

pipeline = [
    { "$match": {"name": "somename"} },
    { "$unwind": { "path": "$values", "includeArrayIndex": "position" } },
    {
        "$project": {
            "name": 1,
            "newarray.position": "$position",
            "newarray.user_name": "$values.user_name",
            "newarray.value_date": "$values.value_date",
            "newarray.value": "$values.value",
        }
    },
    {
        "$group": {
            "_id": "$name",
            "values": { "$push": "$newarray" }
        }
    }    
]
db.test.aggregate(pipeline);

<强>输出

> db.test.aggregate(pipeline).pretty();
{
        "_id" : "somename",
        "values" : [
                {
                        "position" : NumberLong(0),
                        "user_name" : "guest8911",
                        "value_date" : "2016-03-09T14:40:34.512Z",
                        "value" : 8911
                },
                {
                        "position" : NumberLong(1),
                        "user_name" : "guest7485",
                        "value_date" : "2016-03-07T14:11:05.217Z",
                        "value" : 539
                },
                {
                        "position" : NumberLong(2),
                        "user_name" : "guest7485",
                        "value_date" : "2016-03-07T14:11:08.853Z",
                        "value" : 221
                },
                {
                        "position" : NumberLong(3),
                        "user_name" : "guest7485",
                        "value_date" : "2016-03-07T14:11:12.377Z",
                        "value" : 77
                }
        ]
}
>

如果mgo驱动程序不支持这种方法,那么一种不那么有效的方法就是使用Map-Reduce。以下mongo shell示例演示了如何运行该操作:

填充测试集合:

db.test.insert({ 
    "name": "somename", 
    "values": [
        {
          "user_name": "guest8911",
          "value": 8911,
          "value_date": "2016-03-09T14:40:34.512Z"
        },
        {
          "user_name": "guest7485",
          "value": 539,
          "value_date": "2016-03-07T14:11:05.217Z"
        },
        {
          "user_name": "guest7485",
          "value": 221,
          "value_date": "2016-03-07T14:11:08.853Z"
        },
        {
          "user_name": "guest7485",
          "value": 77,
          "value_date": "2016-03-07T14:11:12.377Z"
        }
      ]
})

运行以下map-reduce操作:

> mr = db.runCommand({
    "mapreduce": "test",
    "map": function() {
        var arr = []
        for(var i=0; i < this.values.length; i++){
            var val = this.values[i];
            val["position"] = i+1;
            arr.push(val);
        }
        emit(this._id, arr);
    },
    "reduce" : function() {}, 
    "out": "test_keys"
})

查询结果集合:

> db[mr.result].find().pretty()
{
        "_id" : ObjectId("56e18ab84b9018ec86d2a6bd"),
        "value" : [
                {
                        "user_name" : "guest8911",
                        "value" : 8911,
                        "value_date" : "2016-03-09T14:40:34.512Z",
                        "position" : 1
                },
                {
                        "user_name" : "guest7485",
                        "value" : 539,
                        "value_date" : "2016-03-07T14:11:05.217Z",
                        "position" : 2
                },
                {
                        "user_name" : "guest7485",
                        "value" : 221,
                        "value_date" : "2016-03-07T14:11:08.853Z",
                        "position" : 3
                },
                {
                        "user_name" : "guest7485",
                        "value" : 77,
                        "value_date" : "2016-03-07T14:11:12.377Z",
                        "position" : 4
                }
        ]
}
>

现在给出上面的列表,您可以使用MapReduce

在mgo中汇编查询
job := mgo.MapReduce{
      Map:    "function(){var arr=[];for(var i=0;i<this.values.length; i++){var val=this.values[i];val['position']=i+1;arr.push(val);};emit(this._id,arr);}",
      Reduce: "function() { }",
  }
  var result []struct { Id int "_id"; Value []EValue }
  _, err := collection.Find(nil).MapReduce(job, &result)
  if err != nil {
      panic(err)
  }
  for _, item := range result {
      fmt.Println(item.Value)
  }

有关详细信息,请查看文档:{​​{3}}: