MongoDB query (4) - cursor and paging [8]

Please reprint from the source: http://eksliang.iteye.com/blog/2177567

1. Cursor

        The database uses the cursor to return the result of the find execution. The implementation of the cursor on the client can usually effectively control the final result. Defining a cursor from the shell is very simple, that is, assigning the query result to a variable (the variable declared with var is a local variable), and then creating a cursor, as follows shown:

> var cursor = db.users.find()

       The advantage of this is that you can view one result at a time. If the above query result is placed in a global variable or not in a variable at all, the MongoDB shell will automatically iterate and display the first few documents automatically.

 

You can use the cursor's next() method to get the next piece of data. Use the hasNext() method to see if there is still data in the cursor.

Reference example 1: while iteration cursor

var cursor = db.users.find().limit(10);
while(cursor.hasNext()){
	user=cursor.next();
	print(user.name);
}

 Reference example 2: forEach iteration cursor

var cursor = db.users.find().limit(10);
cursor.forEach(function(user){
	print(user.name);
});

       When the find() method is called, the shell does not query the database immediately, but waits until it actually starts asking for results before sending the query, so that additional options can be attached to the query before execution. Almost every method of a cursor object returns the cursor itself, so that method chains can be formed in any order. For example, the following expressions are equivalent.

> var cursor=db.users.find().sort({"age":1}).limit(10).skip(10)
> var cursor=db.users.find().skip(10).limit(10).sort({"age":1})

       At this point the above query has not sent a request to the database, they are just constructing the query. Now, suppose we do the following:

> cursor.hasNext()

      At this point, the query is sent to the server. The shell immediately obtains 100 pieces of data or the first 4M of data (the smaller of the two), so that the next time next or hasNext is called, there is no need to connect to the server again to obtain the result. When the client runs out of the first set of results, the shell contacts the database again.

 

Second, the life cycle of the cursor

       There are two ways to look at cursors: "client-side cursors" and "server-side cursors over which the client requested the past." On the server-side, cursors consume memory and other resources. So we talk about the server side, the client side is meaningless. When the client initiates a query find() to the server, it means that a cursor is created on the server side. The following three cases will cause the cursor to be destroyed.

  • When the cursor has been traversed, or the client sends a message to request termination, the database will release these resources.
  • When the client's cursor is out of scope, the driver sends a special message to the server to destroy the cursor.
  • When the server does not operate the cursor within 10 minutes, even if the client cursor is in the scope or has not been iterated, the database will automatically destroy the cursor.

3., imit, skip and sort

  • limit: used to limit the returned results and return the upper limit of matching documents
  • skip: how many documents to skip ahead
  • sort: parameter to sort

These options must be specified before the query is sent to the server

Reference example: paging query the second page of the users collection with 10 records per page, and specify the ascending order of age

> var cursor=db.users.find().skip(10).limit(10).sort({"age":1})
> cursor.forEach(function(user){
... print("userName:"+user.name+" age:"+user.age);
... });

 The returned results are as follows:

userName:user2088 age:11
userName:user2212 age:12
userName:user2371 age:13
userName:user2655 age:14
userName:user2681 age:15
userName:user2855 age:16
userName:user3186 age:17
userName:user3332 age:18
userName:user3383 age:19
userName:user3465 age:20

 

 

 四、怎么对mongodb进行分页

      当使用skip略过少量文档还是不错的。但是要是数量非常多的话,skip会变得相当慢,例如想返回第10000页(每页20条记录),MongoDB必须先找到200000条记录,然后再抛弃199920条数据,这种分页需求在业内也有一个名词叫做“深分页”。大多数数据库都会再索引中保存更多的元数据,用于处理skip(Solr 4.7.1也引入了游标处理这种深分页),所以要尽量避免滤过太多数据。

 

既然MongoDB的skip不适合做深分页,那怎么做呢?

答:MongoDB能不能做深分页这取决于查询本身。

根据一般业务来讲,可以找到一种方法在不使用skip的情况下实现分页,这主要取决于查询本身。

参考实例

例如要按照"date"降序显示文档列表。可以按照如下方式获取结果的第一页:

> db.users.find().sort({"create":-1}).limit(10)

 然后利用上次查询的最后一个文档中的"date"值作为查询条件,来获取下一页:

var lastTime=users.last.date;--这个可以根据实际情况获得,我这里只是随便写写,让你感受到这种思想。

获取下一页:

db.users.find({"create":{"$gt":lastTime}}).sort("create":-1}).limit(10)

 这种分页查询中就没有了skip了。

 

优化深分页的核心思想(包括关系型数据库,以及其他NoSql数据库):减少当前查询在结果集里面存放的数据。

 

 

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326396561&siteId=291194637