本文基于 Golang 的爬虫框架 Go-Colly 进行数据抓取,然后存储到 MongoDB 数据库。根据搜索结果,相对来说最成熟的 MongoDB 驱动,应该是 mgo,但是目前 mgo 的作者已经停止维护。另外 MongoDB 官方也已经有对应 Golang 的驱动 mongo-go-driver,但是 Google 上相关的资料并不多。

1. Mgo 驱动

地址: https://godoc.org/labix.org/v2/mgo

地址: https://github.com/globalsign/mgo

文档: https://godoc.org/github.com/globalsign/mgo

说明:上面第一个地址,是 mgo 的原地址,目前作者已经停止维护。第二个地址是基于原作者的社区维护版本,也是作者推荐的方案之一。

2. 官方驱动

地址: https://github.com/mongodb/mongo-go-driver

文档:https://godoc.org/github.com/mongodb/mongo-go-driver/mongo

说明:遇到些问题,相关资料不是很多,尤其是缺少 Demo 可以参考。

3. 官方驱动简单测试

# service/client.go
package mongodb

import (
    "context"
    "fmt"
    "github.com/mongodb/mongo-go-driver/mongo"
    "github.com/mongodb/mongo-go-driver/mongo/findopt"
    "log"
)

const (
    MONGODB  string = "mongodb://localhost:27017"
    DATABASE string = "test"
)

func GetClient() *mongo.Client {
    client, err := mongo.NewClient(MONGODB)
    if err != nil {
        log.Fatal(err)
    }
    err = client.Connect(context.TODO())
    if err != nil {
        log.Fatal(err)
    }
    return client
}

// 查询
func Find(client *mongo.Client, collection_name string, filter interface{}, opt []findopt.Find) mongo.Cursor {
    collection := client.Database(DATABASE).Collection(collection_name)
    cur, err := collection.Find(context.Background(), filter, opt...)
    if err != nil {
        log.Fatal(err)
    }
    defer cur.Close(context.Background())
    return cur
}

// 插入
func Insert(client *mongo.Client, collection_name string, document interface{}) interface{} {
    collection := client.Database(DATABASE).Collection(collection_name)
    res, err := collection.InsertOne(context.Background(), document)
    if err != nil {
        // log.Fatal(err)
        fmt.Print(err)
        return ""
    }
    return res.InsertedID
}

// 查询数量
func Count(client *mongo.Client, collection_name string, filter interface{}) int64 {
    collection := client.Database(DATABASE).Collection(collection_name)
    res, err := collection.Count(context.Background(), filter)
    if err != nil {
        log.Fatal(err)
    }
    return res
}

目前遇到的问题就是,在查询时,不加任何条件,但是每次最多只能返回 101 条数据。

如果配合上 limit(N) ,当 N 大于 101 时,也依然无效。暂时未找到原因。

临时方案就是多次分页查询,比如我每次查询 100 条,多次查询。

# 代码片段
// 数据库
client := mongodb.GetClient()
// 查询商圈
count := mongodb.Count(client, "bizcircle", map[string]interface{}{})
for i := 1; i <= int(math.Ceil(float64(count)/float64(100))); i++ {
    cur := mongodb.Find(client, "bizcircle", map[string]interface{}{}, []findopt.Find{findopt.Skip(int64((i - 1) * 100)), findopt.Limit(100)})
    // 循环遍历
    for cur.Next(context.Background()) {
        elem := bson.NewDocument()
        err := cur.Decode(elem)
        if err != nil {
            log.Fatal(err)
        }
        // 当前商圈
        bizcircleId := elem.LookupElement("bizcircle_id").Value().StringValue()
        // 后续处理
    }
}

标签:Golang / MongoDB