使用REST API进行Cassandra模型分页

时间:2016-08-23 16:19:33

标签: python api model 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,并希望创建包含limitoffset的api。

我检查了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解决方案,哪一个是正确的?

1 个答案:

答案 0 :(得分:3)

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

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

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