本文基于 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 的原地址,目前作者已经停止维护。第二个地址是基于原作者的社区维护版本,也是作者推荐的方案之一。

请参考相关项目中的使用:

https://github.com/phpha/gocolly-beike

本文以下内容请忽略,不建议使用。


### 2. 官方驱动 地址: `https://github.com/mongodb/mongo-go-driver` 文档:`https://godoc.org/github.com/mongodb/mongo-go-driver/mongo` 说明:遇到些问题,相关资料不是很多,尤其是缺少 `Demo` 可以参考。 ### 3. 官方驱动简单测试 ```golang # 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{}, opts ...*options.FindOptions) mongo.Cursor { collection := client.Database(dbName).Collection(collection_name) cur, err := collection.Find(context.Background(), filter, opts...) if err != nil { log.Fatal(err) } defer cur.Close(context.Background()) return cur } // 查询单条 func FindOne(client *mongo.Client, collection_name string, filter interface{}) *bson.Document { collection := client.Database(dbName).Collection(collection_name) result := bson.NewDocument() err := collection.FindOne(context.Background(), filter).Decode(result) if err != nil { log.Fatal(err) } return result } // 计数 func Count(client *mongo.Client, collection_name string, filter interface{}) int64 { collection := client.Database(dbName).Collection(collection_name) res, err := collection.Count(context.Background(), filter) if err != nil { log.Fatal(err) } return res } // 插入 func Insert(client *mongo.Client, collection_name string, document interface{}) interface{} { collection := client.Database(dbName).Collection(collection_name) res, err := collection.InsertOne(context.Background(), document) if err != nil { // fmt.Print(err) return "" } return res.InsertedID } // 更新 func Update(client *mongo.Client, collection_name string, filter interface{}, document interface{}, opts ...*options.FindOneAndUpdateOptions) bool { collection := client.Database(dbName).Collection(collection_name) res := collection.FindOneAndUpdate(context.Background(), filter, document, opts...) if res.Decode(res) != nil { return false } return true } // 删除 func Delete(client *mongo.Client, collection_name string, filter interface{}) int64 { collection := client.Database(dbName).Collection(collection_name) res, err := collection.DeleteOne(context.Background(), filter) if err != nil { log.Fatal(err) } return res.DeletedCount } ``` 目前遇到的问题就是,在查询时,不加任何条件,但是每次最多只能返回 `101` 条数据。 如果配合上 `limit(N)` ,当 `N` 大于 `101` 时,也依然无效。暂时未找到原因。 临时方案就是多次分页查询,比如我每次查询 `100` 条,多次查询。 ```golang // 数据库 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