Ağ uygulamaları için ortak bir görev, kullanıcı girişi ile veritabanındaki bazı verileri aramaktır. Basit bir durumda, bu bir nesnenin listesini bir kategori ile süzebilir. Daha karmaşık bir kullanım örneği, ağırlıklandırma, kategori oluşturma, vurgulama, birden çok dilde arama ve benzeri şeyleri gerektirebilir. Bu belge, olası kullanım durumlarından ve kullanabileceğiniz araçlardan bazılarını açıklamaktadır.
Sorgulama yapma bölümünde kullanılanlarla aynı kalıpları ele alacağız.
Metin tabanlı alanlar, basit eşleme işlemleri için bir seçime sahiptir. Örneğin, böyle bir yazarın araştırımasına izin vermek isteyebilirsiniz:
>>> Author.objects.filter(name__contains='Terry')
[<Author: Terry Gilliam>, <Author: Terry Jones>]
Bu, kullanıcıların yazarın adının tam bir alt dizilimini bilmesini gerektirdiğinden, çok kırılgan bir çözümdür. Daha iyi bir yaklaşım, büyük küçük harf duyarlılığı olmayan bir eşleşme olabilir (icontains), ancak bu sadece marjinal olarak daha iyidir.
PostgreSQL kullanıyorsanız, Django, daha karmaşık sorgulama seçeneklerinden yararlanmanıza izin vermek için veritabanına özel araçlar sunar. Diğer veritabanları, olasılıkla eklentiler veya kullanıcı tanımlı işlevler aracılığıyla farklı araç seçeneklerine sahiptir. Django şu an için herhangi bir destek bulmuyor. Veritabanlarının sahip olabileceği işlevsellik türlerini göstermek için PostgreSQL’in bazı örneklerini kullanacağız.
django.contrib.postgres tarafından sağlanan arama araçlarının tamamı, özel aramalar ve veritabanı işlevleri gibi tamamen ortak API’lerde oluşturulmuştur. Veritabanınıza bağlı olarak, benzer API’lere izin vermek için sorgular oluşturabilmelisiniz. Bu şekilde ulaşılamyacak belirli şeyler varsa, lütfen bir bilet açın.
Yukarıdaki örnekte, büyük küçük harfe duyarsız bir aramanın daha yararlı olacağını belirledik. İngilizce olmayan isimlerle uğraşırken, akıcı olmayan bir karşılaştırmanın kullanılması daha da geniltirilebilir:
>>> Author.objects.filter(name__unaccent__icontains='Helen')
[<Author: Helen Mirren>, <Author: Helena Bonham Carter>, <Author: Hélène Joy>]
Bu, adın farklı bir harflerle eşleştirildiği başka bir orunu gösteriyor. Bu durumda uyumsuzluk var. Helen aramaları Helena ya da Hélène‘i alacak ama tersi değil. Başka bir seçenek ise, harf dizilerini karıştıran trigram_similar karşılaştırmasını kullanmaktır.
Örneğin:
>>> Author.objects.filter(name__unaccent__lower__trigram_similar='Helen')
[<Author: Helen Mirren>, <Author: Hélène Joy>]
Şimdi farklı bir sorunumuz var. Çok daha uzun olduğu gibi “Helena Bonham Carter”‘ın uzun adı görünmüyor. Trigram aramaları, üç harfin tüm olasılıklarını dikkate alır ve kaç tane arama ve kaynak dizesinde gördüğünü karşılaştırır. Daha uzun isimler için, kaynak dizesinde görünen ve dolayısıyla yakın eşleşme olarak nitelendirilmeyen daha fazla olasılık var.
Buradaki karşılaştırma işlevlerinin doğru seçimi, kullandığınız diller ve aranan metin türü gibi belirli veri kümenize bağlıdır. Gördüğümüz örneklerin tamamı, kullanıcıların kaynak verilere yakın (değişen tanımlar verilerek) bir şeyler girmeleri muhtemel kısa dizeler üzerindedir.
Basit veritabanı işlemleri, büyük metin bloklarını düşündüğünüzde çok basit bir yaklaşımdır. Yukarıdaki örnekler, bir dizi karakterle ilgili işlemler olarak düşünülebilirken, tam metin araması gerçek kelimelere bakar. Kullanılan örgüye bağlı olarak, aşağıdaki fikirlerden bazılarını kullanması olasıdır.
Arama yazılımını kullanmak için pek çok seçenek var. Bazıları Elastic ve Solr. Bunlar belge tabanlı arama çözümler. Onları Django modellerinden gelen verilerle sınamak için, verilerinizi bir metinli belgeye, yani veritabanı kimliklerine yapılan geri göndermeleri de içeren bir katmana ihtiyacınız olacak. Motoru kullanan belirli bir arama belgeyi döndürdüğünde, veritabanında arama yapabilirsiniz. Bu işleme yardımcı olmak üzere tasarlanmış çeşitli üçüncü parti kitaplıklar vardır.
PostgreSQL’in dahili olarak tam metin arama uygulaması vardır. Bazı diğer arama motorları kadar güçlü olmasa da, veritabanınızda olmanın avantajı vardır ve bu nedenle kategorileştirme gibi diğer ilişkisel sorgularla kolayca birleştirilebilir.
django.contrib.postgres modülü, bu sorguları yapmak için bazı yardımcılar sağlar. Örneğin, basit bir sorgu “peynir” den bahsedilen tüm blog girişlerini seçmek olabilir:
>>> Entry.objects.filter(body_text__search='cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]
Ayrıca alanları ve ilgili kalıpları bir arada süzebilirsiniz:
>>> Entry.objects.annotate(
... search=SearchVector('blog__tagline', 'body_text'),
... ).filter(search='cheese')
[
<Entry: Cheese on Toast recipes>,
<Entry: Pizza Recipes>,
<Entry: Dairy farming in Argentina>,
]
Ayrıntılı bilgi için contrib.postgres tam metin arama belgesine bakın.