2016-08-23 3 views
0

Ich habe Modell als.Cassandra Modell Paging mit REST API

# 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} 

Ich schrieb Flasche App, die Daten von diesem Modell dienen.

# 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') 

Dieser Code funktioniert gut, und ich bekomme API arbeiten als.

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"}]} 

Jetzt möchte ich pagging hinzufügen und möchten api schaffen, die limit und offset hat.

Ich überprüfe Paging Large Queries, aber es hat kein Beispiel mit Model.

Dann ändere ich meine 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) 
... 
... 

Und api nennen wie:

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"}]} 

und

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"}]} 

ich eine andere Lösung erhalten mit has_more_pages und start_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') 

Von oben 2 Lösung, welche ist richtig?

Antwort

2

Momentan gibt es keine effiziente Möglichkeit, Seitenumbrüche mit CQLEngine durchzuführen. Das Verwenden von QuerySet-Slicing funktioniert, aber beachten Sie, dass vorherige Seiten weiterhin intern im Ergebniscache materialisiert werden. Dies kann zu Speicherproblemen führen und die Anforderungsleistung beeinträchtigen. Ich habe ein Ticket erstellt, um zu analysieren, wie Sie jeweils eine einzelne Seite ausfüllen können. Sie können folgendes Ticket sehen:

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

Wenn Sie eine sofortige effiziente Paginierung Unterstützung benötigen, schlage ich vor, die Kern-Treiber statt cqlengine zu verwenden.

+0

Dank Alan, können Sie Link für Core-Treiber geben? – Nilesh

+0

Hier finden Sie einige Dokumente zum Paging großer Abfragen: https://datastax.github.io/python-driver/query_paging.html. In der nächsten Version (3.7) können Sie das Paging über die Ausführungen paging_state fortsetzen. Siehe https://datastax-oss.atlassian.net/browse/PYTHON-200 –

+0

Alan, ich gab den gleichen Link in meiner Frage, aber ich versuche, einen Weg zu finden, dies zu tun mit 'Model' – Nilesh