对StringProperty的gql查询中的where insensitive where子句

时间:2009-11-01 19:59:08

标签: google-app-engine gql gqlquery

使用google appengine数据存储区,有没有办法执行gql查询,在不区分大小写的StringProperty数据类型上指定WHERE子句?我并不总是确定该值的大小写。文档指定where对我的值区分大小写,是否有办法使这种不敏感?

例如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

3 个答案:

答案 0 :(得分:14)

我认为数据存储区中没有这样的运营商。

您是否控制类别数据的输入?如果是这样,您应该选择一个规范形式来存储它(全部小写或全部大写)。如果由于某种原因需要存储原始案例,那么您可以只存储两列 - 一列是原始列,另一列是标准列。这样你就可以做一个普通的WHERE子句。

答案 1 :(得分:6)

数据存储区不支持不区分大小写的比较,因为您无法索引使用它们的查询(禁止转换值的索引)。彼得建议,除了标准版本之外,解决方案是存储字符串的标准化版本。 AETycoon库中的属性类可能会有所帮助,尤其是DerivedProperty。

答案 2 :(得分:0)

这个帖子很有帮助,让我想用类似的方法做出贡献,使部分搜索匹配成为可能。我在数据存储类型上添加了一个字段,并将标准化短语上的每个单词保存为一组,然后使用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])]))))))