Google App Engine: Apakah mungkin untuk melakukan kueri Gql LIKE?

123

Sederhana sekali. Di SQL, jika saya ingin mencari kolom teks untuk beberapa karakter, saya dapat melakukan:

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

Dokumentasi untuk App Engine tidak menyebutkan cara mencapai ini, tetapi apakah itu masalah yang cukup umum?

littlecharva.dll
sumber
3
Masalah lanjutan berkisar pada orang yang mencoba menggunakan GAE Datastore seolah-olah itu adalah database Relasional / ~ SQL. Dengan diperkenalkannya GQL oleh Google, hal itu semakin mengarahkan orang-orang untuk berpikir tentang sistem SQL. Namun saya memahami bahwa Google sedang mencoba membuat transisi untuk semua orang menjadi lebih mudah meskipun saya tidak yakin ini adalah pendekatan yang tepat.
fuentesjr

Jawaban:

81

BigTable, yang merupakan back end database untuk App Engine, akan menskalakan hingga jutaan rekaman. Karenanya, App Engine tidak akan mengizinkan Anda melakukan kueri apa pun yang akan menghasilkan pemindaian tabel, karena kinerjanya akan sangat buruk untuk tabel yang terisi penuh.

Dengan kata lain, setiap query harus menggunakan indeks. Inilah mengapa Anda hanya bisa melakukan =, >dan <kueri. (Sebenarnya Anda juga bisa melakukannya !=tetapi API melakukannya menggunakan kombinasi kueri >dan <.) Ini juga mengapa lingkungan pengembangan memantau semua kueri yang Anda lakukan dan secara otomatis menambahkan indeks yang hilang keindex.yaml file .

Tidak ada cara untuk mengindeks LIKEkueri sehingga tidak tersedia.

Memiliki jam dari sesi Google IO ini untuk penjelasan yang lebih baik dan lebih rinci ini.

Dave Webb
sumber
77

Saya menghadapi masalah yang sama, tetapi saya menemukan sesuatu di halaman mesin aplikasi google:

Kiat: Filter kueri tidak memiliki cara eksplisit untuk mencocokkan hanya sebagian dari nilai string, tetapi Anda dapat memalsukan pencocokan awalan menggunakan filter ketidaksetaraan:

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

Ini cocok dengan setiap entitas MyModel dengan properti string prop yang dimulai dengan karakter abc. String unicode u "\ ufffd" mewakili kemungkinan karakter Unicode terbesar. Ketika nilai properti diurutkan dalam indeks, nilai yang termasuk dalam kisaran ini adalah semua nilai yang dimulai dengan awalan yang diberikan.

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

mungkin ini bisa berhasil;)

solidsnack
sumber
6
+1 Perlu diperhatikan bahwa ini peka huruf besar-kecil. Untungnya data di bidang yang saya kueri diubah menjadi huruf kecil sebelum disimpan.
Cuga
12

Meskipun App Engine tidak mendukung permintaan SEPERTI, kita lihat sifat ListProperty dan StringListProperty . Saat pengujian kesetaraan dilakukan pada properti ini, pengujian tersebut sebenarnya akan diterapkan pada semua anggota daftar, misalnya, list_property = valuepengujian jika nilai muncul di mana pun dalam daftar.

Terkadang fitur ini dapat digunakan sebagai solusi untuk kurangnya kueri LIKE. Misalnya, ini memungkinkan untuk melakukan pencarian teks sederhana, seperti yang dijelaskan di posting ini .

jbochi
sumber
3
kiriman sudah tidak ada lagi
mwm
9

Anda perlu menggunakan layanan pencarian untuk melakukan kueri pencarian teks lengkap yang mirip dengan SQL LIKE.

Gaelyk menyediakan bahasa khusus domain untuk melakukan kueri penelusuran yang lebih ramah pengguna . Misalnya cuplikan berikut akan menemukan sepuluh buku pertama yang disortir dari yang terbaru dengan judul yang mengandung fern dan genre yang sama persis 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
}

Seperti yang tertulis sebagai operator pertandingan Groovy =~. Ini mendukung fungsi seperti distance(geopoint(lat, lon), location)juga.

musketyr.dll
sumber
3

Lihat Objectify di sini , ini seperti API akses Datastore. Ada FAQ dengan pertanyaan ini secara khusus, inilah jawabannya

Bagaimana cara melakukan kueri seperti (SEPERTI "foo%")
Anda dapat melakukan sesuatu seperti startWith, atau endWith jika Anda membalik urutan saat disimpan dan dicari. Anda melakukan kueri rentang dengan nilai awal yang Anda inginkan, dan nilai tepat di atas nilai yang Anda inginkan.

String start = "foo";
    ... = ofy.query(MyEntity.class).filter("field >=", start).filter("field <", start + "\uFFFD");
fernandohur
sumber
1
itu akan mencari "dimulai dengan" bukan "Berisi".
Hardik Patel
1

Cukup ikuti di sini: init.py # 354 "> http://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/search/ init .py # 354

Berhasil!

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(...)
gzerone
sumber
1

Saya menguji ini dengan API Java tingkat rendah GAE Datastore. Saya dan bekerja dengan sempurna

    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);
Edy Aguirre
sumber
1
ini berfungsi untuk prefiks, tetapi bagaimana jika saya ingin mencocokkan dari akhir string? Misalnya - saya ingin mencari abc di sdfdsabc, maka itu harus mengembalikan sdfdsabc
user1930106
1

Secara umum, meskipun ini adalah posting lama, cara untuk menghasilkan 'LIKE' atau 'ILIKE' adalah dengan mengumpulkan semua hasil dari query '> =', kemudian hasil loop dalam python (atau Java) untuk elemen yang berisi apa yang Anda sedang mencari.

Katakanlah Anda ingin memfilter pengguna yang diberi 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)
chuycepeda
sumber
1

Tidak mungkin melakukan pencarian LIKE di mesin aplikasi datastore, bagaimana pun membuat Arraylist akan berhasil jika Anda perlu mencari kata dalam string.

@Index
    public ArrayList<String> searchName;

dan kemudian untuk mencari di indeks menggunakan objectify.

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

dan ini akan memberi Anda daftar dengan semua item yang berisi dunia yang Anda lakukan pada pencarian

Jose Salas
sumber
0

Jika LIKE '%text%' selalu dibandingkan dengan satu atau beberapa kata (pikirkan permutasi) dan data Anda berubah perlahan (perlahan-lahan berarti tidak terlalu mahal - baik dari segi harga maupun kinerja - untuk membuat dan memperbarui indeks) maka Entitas Indeks Relasi (RIE) mungkin jawabannya.

Ya, Anda harus membangun entitas datastore tambahan dan mengisinya dengan benar. Ya, ada beberapa batasan yang harus Anda mainkan (salah satunya adalah batasan 5000 pada panjang properti daftar di datastore GAE). Namun penelusuran yang dihasilkan sangat cepat.

Untuk detailnya lihat RIE saya dengan Java dan Ojbectify dan RIE dengan posting Python .

topchef
sumber
0

"Suka" sering digunakan sebagai pengganti orang miskin untuk penelusuran teks. Untuk pencarian teks, dimungkinkan untuk menggunakan Whoosh-AppEngine .

amit
sumber