2009-11-01 47 views
11

使用google appengine数据存储,是否有一种方法可以执行gql查询,该查询指定不区分大小写的StringProperty数据类型上的WHERE子句?我并不总是知道价值会在什么情况下发生。文档指出我的价值观在哪里区分大小写,是否有办法让这种感觉不敏感?不区分大小写忽略StringProperty的gql查询中的where子句

例如数据库模型应该是这样的:

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 

回答

13

我不认为在数据存储中有这样的操作符。

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

5

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

+0

我没有写出来的脚本正常化他们。感谢指向图书馆的指针。 – jasonmw 2009-11-02 16:41:39

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])]))))))