2017-01-09 6 views
3

사용자 요청을 기반으로 가능한 기준의 범위 (0-4)에서 데이터 저장소를 쿼리하려고합니다. 다음과 같이 NDB의 쿼리가 내장되어 있습니다 :조건에 따라 동적으로 쿼리를 작성하는 방법은 무엇입니까?

myfilter = [] 
myfilter.push('Account.userid >= 40') 
myfilter.push('Account.userid < 50') 
myfilter.push('Account.name == "John"') 
query = Account.query(*myfilter) 

조건문에 따라 어디서든 0 ~ 4 필터 인수에서있을 수 있습니다 :

query = Account.query(Account.userid >= 40, Account.userid < 50) 

내가 뭔가를 할 수있는 방법이 있나요. 내 가정 (잘못 될 수 있음)은 필터가 필요없는 경우 catch-all (예 : Account.userid == *) 필터를 사용하는 것보다 필터를 생략하는 것이 더 바람직하다는 것입니다.

필터를 연결할 수 있지만 쿼리 개체가 불변이므로이 기능이 도움이되는지 확신하지 못합니다.

답변

1

예, 가능합니다. Filtering by Property Values에서 : 예를 들면 :

대신 하나의 표현에 전체 쿼리 필터를 지정하는 당신은 더 편리 단계를 구축 찾을 수 있습니다

query1 = Account.query() # Retrieve all Account entitites 
query2 = query1.filter(Account.userid >= 40) # Filter on userid >= 40 
query3 = query2.filter(Account.userid < 50) # Filter on userid < 50 too 

query3는 동일합니다 query 변수는 이전 예에서와 같습니다. 쿼리 개체는 불변이므로 query2의 구성은 query1에 영향을주지 않으며 query3 의 구성은 query1 또는 query2에 영향을주지 않습니다.

이러한 증분 쿼리 작성 기술을 사용하여 필요에 따라 필터를 조건부로 추가 할 수 있습니다. (예를 들어, 이것은 전체 AND 선택적 조건 사이 가정)

query = Account.query() # Retrieve all Account entitites 
loggin.error(query) 

if filter_by_userid: 
    query = query.filter(Account.userid >= 40, Account.userid < 50) 
    loggin.error(query) 

if filter_by_username: 
    query = query.filter(Account.name == "John") 
    loggin.error(query) 

loggin.error('Final: %s' % query) 

상기 단편은 특별히 실제로 얻어진 새로운 질의 객체 저장 query 변수 쿼리 객체의 imutability 각각 할당을 활용 각 필터를 적용하여 관련 로그 메시지로 확인되었습니다.

+0

원래 쿼리 개체가 변경 가능하지 않기 때문에이 방법은 작동하지 않을 것이라고 생각했습니다. 그러나 그것을 작동시키는 방법을 찾았습니다. 필터를 사용하지 않더라도 각 필터에 대한 쿼리를 정의해야하기 때문에 매우 우아하지 않습니다. (예를 들어, 특정 필터를 신경 쓰지 않아도 query2를 정의해야합니다.) 어쨌든, 그건 내 목적에 충분하다. – lemontree

+0

"그 특정 필터에 관심이 없다"는 것은 무엇을 의미합니까? –

+0

매개 변수가 동적이고 부등식 필터를 사용하는 경우 색인이 누락 된 것 같습니다 @DanCornilescu? 가능하다고 생각되는 모든 가능한 쿼리를 열거 할 수 있고 각 쿼리에 대한 인덱스를 제공 할 수는 있습니다.이 임의의 쿼리는 데이터 저장소에 적합하지 않은 것 같습니다. – jcjones1515

2

이렇게하는 더 우아한 방법이 있습니다. 그리고 btw는 더 동적입니다.

def build_query_by(ndb_class, filters, sorts): 
    """ 
    ndb_class: the ndb model class to query 
    filters: a list of tuples of properties, operations and values 
    sorts: a list of tuples of properties and order symbol 
    """ 
    q = ndb_class.query() 
    for prop, operation, value in filters: 
     if operation == '==': 
      q = q.filter(getattr(ndb_class, prop) == value) 
     elif operation == '>=': 
      q = q.filter(getattr(ndb_class, prop) >= value) 
     elif operation == '<=': 
      q = q.filter(getattr(ndb_class, prop) <= value) 
     # more operations... 

    for prop, symbol in sorts: 
     if symbol == '-': 
      q = q.order(-getattr(ndb_class, prop)) 
     else: 
      q = q.order(getattr(ndb_class, prop)) 
    return q 
+2

주의 : tho : 둘 이상의 속성에서 비항 등 필터를 사용할 수 없으며 한 속성에서 비항 등 필터를 사용하고 다른 속성에서는 비 순차 필터를 사용할 수 없습니다. 이 답변에 인용 된 다른 제한 사항을 참조하십시오 : http://stackoverflow.com/a/41583096/4495081 코드가 보호 기능을 포함하여 깔끔하게 보이지 않을 수 있습니다. –

+0

@ DanCornilescu 네가 맞아. – janscas