当我们需要读大量数据库数据进行操作时,游标经常是我们的选择之一,其原理是,首次读取数据时只会将所有项数据的index返回回来,然后再分批次读取完整的数据,这样可以避免一次性大量数据读取到服务器中,占用大量内存。同样能够避免大量数据一次性读进内存的方式还有分页查询,但是分页查询存在深翻页问题,会导致越查越慢。另一种游标式翻页(每次记录上一次查询的最后一条,并作为下一次查询的条件之一),这种唯一的缺点就是每次都需要重新做一次查询,但这个损耗也可以基本忽略,但是有一个问题就是,往往这样的条件不好找。
下面说一下在spring-mongo-data下如何使用mongo的游标:
//coreClient 是在mongo配置的地方注入的 com.mongodb.MongoClient
//获取库
val database = coreClient.getDatabase("core")
//获取集合
val collection = database.getCollection("fans_team")
//进行查询
val cursor = collection
.find(
Query.query(Criteria.where("time").lt(time.toDate())).queryObject
)
//排序在这里特别注意,不能放到上Query后面,那样不生效
.sort(Document("fans_user_id",1))
//表示每次从mongo中读取1000条
.batchSize(1000)
.iterator()
//对游标进行遍历
while (cursor.hasNext()) {
val doc = cursor.next()
userIds.add(doc.getInteger("fans_user_id"))
}
需要注意的是,当数据量大的时候一定要使用排序,之前遇到一个问题当程序执行了十几分钟后,程序报一个错误:「游标在mongo中找不到」,查了之后发现mongo中的游标是会超时的,我本来想着既然超时,就根据排序,超时的时候打印出最后一条,然后从最后一条开始让脚本继续往下跑,结果当我加了排序之后,超时的问题没有在出现了。所以当进行时间跨度加大的读取时,最好加上排序,避免游标超时这个问题。