Без учета регистра, где предложение в запросе gql для StringProperty - PullRequest
12 голосов
/ 01 ноября 2009

Используя хранилище данных 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 ]

14 голосов
/ 02 ноября 2009

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

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

6 голосов
/ 02 ноября 2009

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

0 голосов
/ 24 мая 2011

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