使用mongo-go-driver和接口将光标反序列化为数组

时间:2019-06-06 16:14:00

标签: mongodb go

我使用golang创建了一个api,我想创建一些功能测试,为此我创建了一个接口来抽象数据库。但是为此,我需要能够在不知道类型的情况下将游标转换为数组。


func (self *KeyController) GetKey(c echo.Context) (err error) {
    var res []dto.Key
    err = db.Keys.Find(bson.M{}, 10, 0, &res)
    if err != nil {
        fmt.Println(err)
        return c.String(http.StatusInternalServerError, "internal error")
    }
    c.JSON(http.StatusOK, res)
    return
}
//THE FIND FUNCTION ON THE DB PACKAGE
func (s MongoCollection) Find(filter bson.M, limit int, offset int, res interface{}) (err error) {
    ctx := context.Background()
    var cursor *mongo.Cursor
    l := int64(limit)
    o := int64(offset)
    objectType := reflect.TypeOf(res).Elem()
    cursor, err = s.c.Find(ctx, filter, &options.FindOptions{
        Limit: &l,
        Skip:  &o,
    })

    if err != nil {
        return
    }

    defer cursor.Close(ctx)

    for cursor.Next(ctx) {
        result := reflect.New(objectType).Interface()
        err := cursor.Decode(&result)
        if err != nil {
            panic(err)
        }
        res = append(res.([]interface{}), result)

    }
    return
}


有人有主意吗?

2 个答案:

答案 0 :(得分:0)

您可以直接调用“全部”方法:

ctx := context.Background()
err = cursor.All(ctx, res)
if err != nil {
    fmt.Println(err.Error())
}

供参考:

https://godoc.org/go.mongodb.org/mongo-driver/mongo#Cursor.All

答案 1 :(得分:0)

我认为您想封装Find方法用于mongo查询。

使用反射包,我通过添加附加参数来实例化切片项目的新实例,从而改进了代码。

func (m *MongoDbModel) FindAll(database string, colname string, obj interface{}, parameter map[string]interface{}) ([]interface{}, error) {
    var list = make([]interface{}, 0)

    collection, err := m.Client.Database(database).Collection(colname).Clone()

    objectType := reflect.TypeOf(obj).Elem()

    fmt.Println("objectype", objectType)
    if err != nil {
        log.Println(err)
        return nil, err
    }

    filter := bson.M{}

    filter["$and"] = []bson.M{}

    for key, value := range parameter {
        filter["$and"] = append(filter["$and"].([]bson.M), bson.M{key: value})
    }

    cur, err := collection.Find(context.Background(), filter)
    if err != nil {
        log.Fatal(err)
    }
    defer cur.Close(context.Background())
    for cur.Next(context.Background()) {
        result := reflect.New(objectType).Interface()
        err := cur.Decode(result)

        if err != nil {
            log.Println(err)
            return nil, err
        }

        list = append(list, result)
    }
    if err := cur.Err(); err != nil {
        return nil, err
    }
    return list, nil
}

区别在于FindAll方法返回[]interface{},其中err := cur.Decode(result)直接使用指针,类似于result变量。