例如:字段A 因为A的类型不确定,可能是map也可能是其他数据类型,所以数据结构定义为 interface类型,但当使用mongo数据库保存时可能出现如下状况:
保存时A字段为 map{“age”:10},查询时使用mongo库(go.mongodb.org/mongo-driver/mongo)解析时获取数据为 [{“key”:“age”,“value”:10}].
以上情况的原因是A字段定义类型为interface{},当使用mongo-driver库解析时从数据获取的数据并不是按照保存时的map来解析的,这就导致了保存和获取时数据不一致的问题。要解决这一问题,需要引入其他的bson库进行解析,我使用的是(“labix.org/v2/mgo/bson”)库。
1) 如果是查询单个数据,可以如下解析:
type QueryStruct struct{
A interface{} `json:"a" bson:"a"`
}
func FindOne(ctx context.Context, filter bson.M) (*QueryStruct, error) {
var val QueryStruct
ret, err := mongodb.Mgo.FindOne(ctx, "collName", filter)
if err == mongo.ErrNoDocuments {
return nil, nil
}
if err != nil {
return nil, err
}
bts, err := ret.DecodeBytes()
if err != nil {
return nil, err
}
err = lbson.Unmarshal(bts, &val)
if err != nil {
return nil, err
}
return &val, nil
}
- 如果是查询多条数据,可以如下解析:
type QueryStruct struct{
A interface{} `json:"a" bson:"a"`
}
func FindMany(ctx context.Context, filter bson.M, opts *options.FindOptions) ([]QueryStruct, error) {
var vals = []entity.ThingModel{}
cur, err := mongodb.Mgo.Find(ctx, "collName", filter, opts)
if err != nil {
return vals, err
}
defer cur.Close(context.TODO())
for cur.Next(context.Background()) {
var bsonM bson.M
err := cur.Decode(&bsonM)
if err != nil {
return vals, err
}
bts, _ := bson.Marshal(bsonM)
var val QueryStruct
err = lbson.Unmarshal(bts, &val)
if err != nil {
return vals, err
}
vals = append(vals, val)
}
return vals, nil
}