How do I transform a document before I assign it to a structure in Go using MongoDB?

huangapple go评论92阅读模式
英文:

How do I transform a document before I assign it to a structure in Go using MongoDB?

问题

我正在使用Go和MongoDB编写一个多语言API。我有一个MongoDB文档,格式如下:

{
  _id : ObjectID(bla)
  "key" : {
    "en" : "Hello",
    "es" : "Hola"
  }
}

然而,API需要以以下形式返回JSON:

{
  _id : ObjectID(bla),
  "key" : "Hola"
}

如果客户端发送语言头。

有没有一种简单/高效的方法来实现这个?我目前唯一有效的解决方案是使用两个单独的结构体,然后使用一堆switch/case语句将它们合并在一起,像这样:

var api MyStruct
var mgo MyMgoStruct
session.DB("db").C("col").Find(nil).One(&mgo)

api.ID = mgo.ID
switch lang {
  default:
    {
      api.Key = string(mgo.Key.En)
    }
  case "es":
    {
      api.Key = string(mgo.Key.Es)
    }
}

结构体定义:

type Translation struct {
  En string `bson:"en"`
  Es string `bson:"es"`
}

type MyStruct struct {
  ID bson.ObjectID `json:"_id" bson:"_id"`
  Key string `json:"key" bson:"key"`
}

type MyMgoStruct struct {
  ID bson.ObjectID `json:"_id" bson:"_id"`
  Key Translation `json:"key" bson:"key"`
}

我预见到这将成为一个巨大的维护负担,因为我的结构体有数十个需要翻译的字段。我希望能找到一种方法来转换MongoDB文档,将Translation的JSON结构替换为MyStruct结构中的简单键值对。

英文:

I am writing a multilingual API with go and mongodb. I have a mongo db document with format:

{
  _id : ObjectID(bla)
  "key" : {
    "en" : "Hello",
    "es" : "Hola"
  }
}

However, the API needs report json in the form:

{
  _id : ObjectID(bla),
  "key" : "Hola"
}

if the client sends language headers.

Is there an easy/efficent way to do this? The only working solution I have is to make two separate structs and then merge them together with a bunch of switch/case statements, like:

var api MyStruct
var mgo MyMgoStruct
session.DB("db").C("col").Find(nil).One(&mgo)

api.ID = mgo.ID
switch lang {
  default:
    {
      api.Key = string(mgo.Key.En)
    }
  case "es":
    {
      api.Key = string(mgo.Key.Es)
    }
}

Structure defs:

type Translation struct {
  En string `bson:"en"`
  Es string `bson:"es"`
}

type MyStruct struct {
  ID bson.ObjectID `json:"_id" bson:"_id"`
  Key string `json:"key" bson:"key"`
}

type MyMgoStruct struct {
  ID bson.ObjectID `json:"_id" bson:"_id"`
  Key Translation `json:"key" bson:"key"`
}

I foresee this becoming a huge pain to maintain, as my structures have tens of translated fields. I would prefer a way to transform the MongoDB document, replacing the Translation json structure with a simple key-value pair as in the MyStruct struct.

答案1

得分: 1

我唯一的有效解决方案是创建两个单独的结构体,然后使用一系列的switch/case语句将它们合并在一起。

另一种方法是使用MongoDB的投影功能在Find()方法上进行操作。以你的示例文档格式为例:

// 客户端输入的语言头部作为变量
var languageInput = "es"

// 拼接以获取嵌套字段 'key'
key := "key." + languageInput

// 仅投影特定字段
cursor := coll.Find(nil).Select(bson.M{key: 1})

参见 从查询结果中投影字段

如果你的结构体中有许多不想映射的翻译字段,你可以利用 bson inline。例如:

type MyStruct struct {
ID bson.ObjectId json:"id" bson:"_id"
OtherFields bson.M bson:",inline"
}

这将捕获 OtherFields 中的非结构化字段。参见 bson.Marshal

英文:

> The only working solution I have is to make two separate structs and then merge them together with a bunch of switch/case statements

An alternative is you could use MongoDB projection on the Find(). Given your example document format, for example:

// Client input language header as variable
var languageInput = "es"  

// Concatenate to get field nest 'key'
key := "key." + languageInput 

// Only project the specific fields
cursor := coll.Find(nil).Select(bson.M{key: 1}) 

See also Project fields to return from query

If you have many translation fields in your struct that you don't want to map, you could utilise bson inline. For example:

type MyStruct struct {
	ID          bson.ObjectId      `json:"id" bson:"_id"`
	OtherFields bson.M             `bson:",inline"`
}

This would capture unstructured fields in OtherFields. See also bson.Marshal

huangapple
  • 本文由 发表于 2017年6月9日 15:49:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/44452211.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定