【问题标题】:Golang get array index value in json responseGolang在json响应中获取数组索引值
【发布时间】: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

【问题讨论】:

  • @aacanakin 我知道 .Iter() 但我再次不确定如何将位置注入 json 响应。
  • 显示 EValues 的定义。
  • @MuffinTop 添加了定义。

标签: arrays json mongodb sorting go


【解决方案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:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-20
    • 2017-10-17
    • 1970-01-01
    • 2019-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多