2016-08-23 66 views
0

我的模型为。使用REST API的Cassandra模型分页

# File: models.py 
from uuid import uuid4 

from cassandra.cqlengine.models import Model 
from cassandra.cqlengine import columns 


class StudentModel(Model): 
    __table_name__ = 'students' 
    id = columns.UUID(primary_key=True, default=uuid4) 
    name = columns.Text(index=True, required=True) 

    def __json__(self): 
     return {'id': str(self.id), 
       'name': self.name} 

我写了瓶子应用程序,从这个模型中提供数据。

# File: app.py 
from bottle import run 
from bottle import Bottle, request, HTTPResponse 

from cassandra.cqlengine import connection 
from cassandra.cqlengine.management import sync_table 

from models import StudentModel 

API = Bottle() 

# Create Connection 
connection.setup(hosts=['192.168.99.100'], 
       default_keyspace='test', 
       protocol_version=3) 

# Sync database table to create table in keyspace 
sync_table(StudentModel) 

@API.get('/students') 
def get_all_students(): 
    all_objs = StudentModel.all() 
    return HTTPResponse(
      body={'data': [x.__json__() for x in all_objs]}, 
      headers={'content-type': 'application/json'}, 
      status_code=200) 

run(host='localhost', 
    port=8080, 
    app=API, 
    server='auto') 

此代码工作正常,我得到的API作为。

curl http://localhost:8080/students -i 
HTTP/1.1 200 OK 
Content-Length: 74 
Content-Type: application/json 
Date: Tue, 23 Aug 2016 15:55:23 GMT 
Server: waitress 
Status-Code: 200 

{"data": [{"id": "7f6d18ec-bf24-4583-a06b-b9f55a4dc6e8", "name": "test"}, {"id": "7f6d18ec-bf24-4583-a06b-b9f55a4dc6e9", "name": "test1"}]} 

现在我想补充pagging,并希望创建API,它具有limitoffset

我检查Paging Large Queries但它没有Model的例子。

然后我就按照API更改为:

# File: app.py 
... 
... 
@API.get('/students') 
def get_all_students(): 
    limit = request.query.limit 
    offset = request.query.offset 

    all_objs = StudentModel.all() 
    if limit and offset: 
     all_objs = all_objs[int(offset): int(offset+limit)] 

    return HTTPResponse(
      body={'data': [x.__json__() for x in all_objs]}, 
      headers={'content-type': 'application/json'}, 
      status_code=200) 
... 
... 

并调用API为:

curl "http://localhost:8080/students?limit=1&offset=0" -i 
HTTP/1.1 200 OK 
Content-Length: 74 
Content-Type: application/json 
Date: Tue, 23 Aug 2016 16:12:00 GMT 
Server: waitress 
Status-Code: 200 

{"data": [{"id": "7f6d18ec-bf24-4583-a06b-b9f55a4dc6e8", "name": "test"}]} 

curl "http://localhost:8080/students?limit=1&offset=1" -i 
HTTP/1.1 200 OK 
Content-Length: 75 
Content-Type: application/json 
Date: Tue, 23 Aug 2016 16:12:06 GMT 
Server: waitress 
Status-Code: 200 

{"data": [{"id": "7f6d18ec-bf24-4583-a06b-b9f55a4dc6e9", "name": "test1"}]} 

我使用has_more_pagesstart_fetching_next_page()

得到另一种解决方案
from bottle import run 
from bottle import Bottle, request, HTTPResponse 

from cassandra.cqlengine import connection 
from cassandra.query import SimpleStatement 
from cassandra.cqlengine.management import sync_table 

from models import StudentModel 

API = Bottle() 

# Create Connection 
connection.setup(hosts=['192.168.99.100'], 
       default_keyspace='test', 
       protocol_version=3) 

# Sync database table to create table in keyspace 
sync_table(StudentModel) 

@API.get('/students') 
def get_all_students(): 
    limit = request.query.limit 
    offset = request.query.offset 

    page = int(request.query.page or 0) 

    session = connection.get_session() 
    session.default_fetch_size = 1 

    objs = StudentModel.all() 

    result = objs._execute(objs._select_query()) 

    data = [] 
    count = 0 
    while (not page or page > count) and result.has_more_pages: 
     count += 1 
     if page and page > count: 
      result.fetch_next_page() 
      continue 

     data.extend(result.current_rows) 
     result.fetch_next_page() 
    all_objs = [StudentModel(**student) for student in data] 

    return HTTPResponse(
      body={'data': [x.__json__() for x in all_objs]}, 
      headers={'content-type': 'application/json'}, 
      status_code=200) 

run(host='localhost', 
    port=8080, 
    app=API, 
    debug=True, 
    server='auto') 

从以上2个解决方案中,哪一个是正确的?

回答

2

目前,没有有效的方式来与CQLEngine分页。使用QuerySet切片工作,但请注意,以前的页面仍将在结果缓存中内部实现。所以,这可能会导致内存问题,并且也会影响请求性能。我创建了一张票来分析一次填充单个页面的方式。你可以看下面的门票:

https://datastax-oss.atlassian.net/browse/PYTHON-627

如果您需要立即有效的分页支持,我建议使用的核心驱动因素,而不是cqlengine的。

+0

谢谢艾伦,你能给链接核心驱动程序? – Nilesh

+0

以下是关于分页大型查询的一些文档:https://datastax.github.io/python-driver/query_paging.html。 在下一个版本(3.7)中,您将能够在执行paging_state之后恢复分页。请参阅https://datastax-oss.atlassian.net/browse/PYTHON-200 –

+0

艾伦,我给了我的问题相同的链接,但我试图找到方式来使用'型号' – Nilesh