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

Posted

技术标签:

【中文标题】Golang在json响应中获取数组索引值【英文标题】:Golang get array index value in json response 【发布时间】:2016-06-25 11:14:06 【问题描述】:

所以我对数据库(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 响应中,我需要添加参数“位置”,对于所有结果,它应该基本上等于 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

【问题讨论】:

你检查过这个吗?***.com/questions/32908186/… @aacanakin 我知道 .Iter() 但我再次不确定如何将位置注入 json 响应。 显示 EValues 的定义。 @MuffinTop 添加了定义。 【参考方案1】:

给EValue添加一个位置字段:

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

遍历db结果并设置字段:

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

将结果编组为 JSON。

【讨论】:

这是最有效的方法吗,因为我真的不喜欢再次遍历整个数组的想法? 这可能是最有效的方式。即使不是,与解组 BSON 值或编组 JSON 值的成本相比,成本也可以忽略不计。【参考方案2】:

在 MongDB 3.2 中,这可以使用 $unwind 运算符来完成,您可以在其中传递带有字段 path 和字段 includeArrayIndex 的对象,该字段将保存数组索引: p>

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)
  

更多详情请查看文档:https://godoc.org/labix.org/v1/mgo#MapReduce:

【讨论】:

以上是关于Golang在json响应中获取数组索引值的主要内容,如果未能解决你的问题,请参考以下文章

golang 怎么设置数组获取任意一个值

生成 JSON API 响应后,数字数组索引丢失

jmeter中用json提取器提取响应数据中的多个值

如何使用 Guzzle 和 Laravel 从 JSON 响应中提取单个数组值

如何实现 JSON 解析代码以获取对 NSArray 的响应?

JSON 数组 Swift 的索引