2016-08-23 63 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