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

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

например, db Model будет следующим:

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

Ответ 1

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

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

Ответ 2

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

Ответ 3

Этот поток был полезен и заставляет меня хотеть внести свой вклад в подобный подход, чтобы сделать возможное частичное совпадение. Я добавляю еще одно поле в виде хранилища данных и сохраняю каждое слово в нормализованной фразе как набор, а затем использую фильтр 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])]))))))