Google App Engine : Gql LIKE 쿼리를 수행 할 수 있습니까?


123

정말 간단합니다. SQL에서 몇 개의 문자에 대한 텍스트 필드를 검색하려면 다음을 수행 할 수 있습니다.

SELECT blah FROM blah WHERE blah LIKE '%text%'

App Engine의 문서에는이를 달성하는 방법에 대한 언급이 없지만 확실히 일반적인 문제입니까?


3
계속되는 문제는 마치 관계형 / ~ SQL 데이터베이스 인 것처럼 GAE Datastore를 사용하려는 사람들과 관련되어 있습니다. Google이 GQL을 도입함으로써 사람들이 SQL 시스템 측면에서 생각하도록 유도합니다. 그러나 이것이 올바른 접근 방식인지 확실하지 않지만 Google이 모든 사람을 위해 훨씬 쉽게 전환하려고 노력하고 있음을 이해합니다.
fuentesjr

답변:


81

App Engine의 데이터베이스 백엔드 인 BigTable은 수백만 개의 레코드로 확장됩니다. 이로 인해 App Engine은 테이블 스캔을 초래하는 쿼리를 수행하는 것을 허용하지 않습니다. 잘 채워진 테이블의 성능은 두려울 것입니다.

즉, 모든 쿼리는 인덱스를 사용해야합니다. 이것이 =, ><쿼리 만 수행 할 수있는 이유 입니다. (실제로 할 수 !=있지만 API는 ><쿼리의 조합을 사용하여이 작업을 수행 합니다.) 이것이 개발 환경이 사용자가 수행하는 모든 쿼리를 모니터링하고 누락 된 인덱스를 index.yaml파일에 자동으로 추가하는 이유이기도 합니다.

LIKE쿼리 를 인덱싱 할 수있는 방법이 없으므로 단순히 사용할 수 없습니다.

이에 대한 훨씬 더 좋고 자세한 설명을 보려면 이 Google IO 세션 을 시청 하십시오.


77

동일한 문제에 직면했지만 Google 앱 엔진 페이지에서 뭔가를 발견했습니다.

팁 : 쿼리 필터에는 문자열 값의 일부만 일치시키는 명시적인 방법이 없지만 비 균등 필터를 사용하여 접두사 일치를 가짜로 만들 수 있습니다.

db.GqlQuery("SELECT * FROM MyModel WHERE prop >= :1 AND prop < :2",
            "abc",
            u"abc" + u"\ufffd")

이것은 문자 abc로 시작하는 문자열 속성 prop이있는 모든 MyModel 엔티티와 일치합니다. 유니 코드 문자열 u "\ ufffd"는 가능한 가장 큰 유니 코드 문자를 나타냅니다. 속성 값이 인덱스로 정렬 될 때이 범위에 속하는 값은 주어진 접두사로 시작하는 모든 값입니다.

http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html

어쩌면 이것은 트릭을 할 수 있습니다.)


6
+1 Tho 이것은 대소 문자를 구분한다는 점을 지적 할 가치가 있습니다. 다행히 내가 쿼리하는 필드의 데이터는 저장하기 전에 소문자로 변환됩니다.
Cuga 2011-06-02

12

App Engine은 LIKE 쿼리를 지원하지 않지만 ListPropertyStringListProperty 속성을 살펴보세요 . 이러한 속성에 대해 동등성 테스트가 수행되면 테스트는 실제로 모든 목록 멤버에 적용됩니다. 예를 들어 list_property = value값이 목록의 아무 곳에 나 나타나는지 테스트합니다.

때때로이 기능은 LIKE 쿼리 부족에 대한 해결 방법으로 사용될 수 있습니다. 예를 들어, 이 게시물에 설명 된대로 간단한 텍스트 검색 을 수행 할 수 있습니다 .


3
포스트는 더 이상 존재하지 않습니다
MWM

9

SQL과 유사한 전체 텍스트 검색 쿼리를 수행 하려면 검색 서비스 를 사용해야 합니다 LIKE.

Gaelyk 은보다 사용자 친화적 인 검색 쿼리 를 수행하기 위해 도메인 별 언어를 제공 합니다 . 예를 들어 다음 스 니펫은 제목이 포함 fern 되고 장르가 정확히 일치하는 최신 책에서 정렬 된 처음 10 권의 책을 찾습니다 thriller.

def documents = search.search {
    select all from books
    sort desc by published, SearchApiLimits.MINIMUM_DATE_VALUE
    where title =~ 'fern'
    and genre =  'thriller'
    limit 10
}

Like는 Groovy의 일치 연산자로 작성됩니다 =~. distance(geopoint(lat, lon), location)뿐만 아니라 같은 기능을 지원합니다 .



3

여기 에서 Objectify를 살펴보세요 . 데이터 저장소 액세스 API와 같습니다. 이 질문에 대한 FAQ가 있습니다. 여기에 답변이 있습니다.

like 쿼리를 수행하는 방법 (LIKE "foo %")
저장 및 검색 할 때 순서를 반대로하면 startWith 또는 endWith와 같은 작업을 수행 할 수 있습니다. 원하는 시작 값과 원하는 값 바로 위의 값으로 범위 쿼리를 수행합니다.

String start = "foo";
    ... = ofy.query(MyEntity.class).filter("field >=", start).filter("field <", start + "\uFFFD");

1
"포함"이 아닌 "다음으로 시작"을 검색합니다.
Hardik Patel 2017

1

여기를 따르십시오 : init.py # 354 "> http://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/search/ init .py # 354

효과가있다!

class Article(search.SearchableModel):
    text = db.TextProperty()
    ...

  article = Article(text=...)
  article.save()

To search the full text index, use the SearchableModel.all() method to get an
instance of SearchableModel.Query, which subclasses db.Query. Use its search()
method to provide a search query, in addition to any other filters or sort
orders, e.g.:

  query = article.all().search('a search query').filter(...).order(...)

1

GAE Datastore 하위 수준 Java API로 이것을 테스트했습니다. 나와 완벽하게 작동합니다.

    Query q = new Query(Directorio.class.getSimpleName());

    Filter filterNombreGreater = new FilterPredicate("nombre", FilterOperator.GREATER_THAN_OR_EQUAL, query);
    Filter filterNombreLess = new FilterPredicate("nombre", FilterOperator.LESS_THAN, query+"\uFFFD");
    Filter filterNombre =  CompositeFilterOperator.and(filterNombreGreater, filterNombreLess);

    q.setFilter(filter);

1
이것은 접두사에 대해 작동하지만 문자열 끝에서 일치하려면 어떻게해야합니까? 예를 들어-sdfdsabc에서 abc를 검색하려면 sdfdsabc를 반환해야합니다
user1930106

1

일반적으로 이것은 오래된 게시물이지만 'LIKE'또는 'ILIKE'를 생성하는 방법은 '> ='쿼리에서 모든 결과를 수집 한 다음 사용자가 포함 된 요소에 대해 Python (또는 Java)에서 결과를 루프하는 것입니다. 찾고 있습니다.

aq = 'luigi'가 주어지면 사용자를 필터링한다고 가정 해 보겠습니다.

users = []
qry = self.user_model.query(ndb.OR(self.user_model.name >= q.lower(),self.user_model.email >= q.lower(),self.user_model.username >= q.lower()))

for _qry in qry:
 if q.lower() in _qry.name.lower() or q.lower() in _qry.email.lower() or q.lower() in _qry.username.lower():
      users.append(_qry)

1

데이터 저장소 앱 엔진에서 LIKE 검색을 수행하는 것은 불가능합니다. 문자열에서 단어를 검색해야하는 경우 Arraylist를 만드는 것이 트릭을 수행하는 방법입니다.

@Index
    public ArrayList<String> searchName;

그런 다음 objectify를 사용하여 색인에서 검색합니다.

List<Profiles> list1 = ofy().load().type(Profiles.class).filter("searchName =",search).list();

그러면 검색에서 수행 한 세계를 포함하는 모든 항목이 포함 된 목록이 제공됩니다.


0

LIKE '%text%'항상 한 단어 또는 몇 단어와 비교하고 (순열을 생각하십시오) 데이터가 느리게 변경되는 경우 (천천히 비용 측면과 성능 측면 모두에서 인덱스를 생성하고 업데이트하는 데 엄청나게 비싸지 않음을 의미 함) 관계 인덱스 엔터티 (RIE) 답이 될 수 있습니다.

예, 추가 데이터 저장소 항목을 빌드하고 적절하게 채워야합니다. 예, 몇 가지 제약이 있습니다 (하나는 GAE 데이터 저장소의 목록 속성 길이에 대한 5000 제한). 그러나 검색 결과는 번개처럼 빠릅니다.

자세한 내용은 Java 및 Ojbectify 를 사용한 RIE 및 Python 게시물을 사용한 RIE 를 참조하십시오 .


0

"좋아요"는 종종 텍스트 검색 대신 가난한 사람을 대신하여 사용합니다. 텍스트 검색의 경우 Whoosh-AppEngine 을 사용할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.