Без учета регистра, где предложение в запросе gql для StringProperty

Используя хранилище данных Google Appengine, есть ли способ выполнить запрос gql, который задает предложение WHERE для типа данных StringProperty, который не зависит от регистра? Я не всегда уверен, в каком случае будет значение. В документах указано, где для моих значений регистр чувствителен, есть ли способ сделать это нечувствительным?

например, модель БД будет такой:

from google.appengine.ext import db
class Product(db.Model):
    id = db.IntegerProperty()
    category = db.StringProperty()

и данные выглядят так:

id         category
===================
1          cat1
2          cat2
3          Cat1
4          CAT1
5          CAT3
6          Cat4
7          CaT1
8          CAT5

я хотел бы сказать

gqlstring = "WHERE category = '{0}'".format('cat1')
returnvalue = Product.gql(gqlstring)

и имеют returnvalue содержать

id         category
===================
1          cat1
3          Cat1
4          CAT1
7          CaT1

3 ответа

Решение

Я не думаю, что в хранилище данных есть такой оператор.

Контролируете ли вы ввод данных категории? Если это так, вы должны выбрать каноническую форму для хранения (все строчные или прописные). Если вам по какой-то причине необходимо сохранить исходный случай, то вы можете просто сохранить два столбца - один с оригиналом, другой со стандартизированным. Таким образом, вы можете сделать нормальное предложение WHERE.

Хранилище данных не поддерживает сравнения без учета регистра, потому что вы не можете индексировать запросы, которые их используют (за исключением индекса, который преобразует значения). Решение состоит в том, чтобы хранить нормализованную версию вашей строки в дополнение к стандартной, как предлагает Питер. Классы свойств в библиотеке AETycoon могут оказаться полезными, в частности DerivedProperty.

Эта ветка была полезной и заставляет меня хотеть внести свой вклад с подобным подходом, чтобы сделать возможным частичное соответствие поиска. Я добавляю еще одно поле для вида хранилища данных и сохраняю каждое слово в нормализованной фразе в виде набора, а затем использую фильтр IN для сопоставления. Это пример с Clojure. Нормализованная часть должна быть легко переведена как минимум в Java (благодаря @raek на #clojure), в то время как взаимодействие с базой данных должно быть конвертируемым в любой язык:

(use '[clojure.contrib.string :only [split lower-case]])
(use '[appengine-magic.services.datastore :as ds])

; initialize datastore kind entity
(ds/defentity AnswerTextfield [value, nvalue, avalue]) 

; normalize and lowercase a string
(defn normalize [string-to-normalize]
  (lower-case
    (apply str
      (remove #(= (Character/getType %) Character/NON_SPACING_MARK)
               (java.text.Normalizer/normalize string-to-normalize java.text.Normalizer$Form/NFKD)))))

; save original value, normalized value and splitted normalized value
(defn textfield-save! [value]
  (ds/save! 
    (let [nvalue (normalize value)]
      (ds/new* AnswerTextfield [value nvalue (split #" " nvalue)]))))

; normalized search
(defn search-normalized [value]
  (ds/query :kind AnswerTextfield
            :filter [(= :nvalue (normalize value))]))

; partial normalized word search
(defn search-partial [value]
  (flatten
    (let [coll []]
      (for [splitted-value (split #" " (normalize value))]
        (merge coll 
          (ds/query :kind AnswerTextfield
                    :filter [(in :avalue [splitted-value])]))))))
Другие вопросы по тегам