2009-11-01 7 views
11

Utilizzando l'archivio dati appengine google, esiste un modo per eseguire una query gql che specifica una clausola WHERE su un tipo di dati StringProperty che non fa distinzione tra maiuscole e minuscole? Non sono sempre sicuro di quale sarà il valore. I documenti specificano che dove è il case sensitive per i miei valori, c'è un modo per renderlo insensibile?Maiuscole/minuscole in cui clausola in gql query per StringProperty

per esempio il Modello db sarebbe questo:

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

ei dati appare così:

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

vorrei dire

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

e hanno returnvalue contengono

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

risposta

13

Non penso che ci sia un operatore simile nel datastore.

È possibile controllare l'immissione dei dati della categoria? In tal caso, dovresti scegliere un modulo canonico per memorizzarlo in (tutto in minuscolo o in maiuscolo). Se è necessario archiviare la custodia originale per qualche motivo, è possibile memorizzare due colonne, una con l'originale e una con quella standard. In questo modo puoi fare una normale clausola WHERE.

5

Il datastore non supporta confronti con distinzione tra maiuscole e minuscole, perché non è possibile indicizzare le query che li utilizzano (escludendo un indice che trasforma valori). La soluzione è quella di memorizzare una versione normalizzata della stringa in aggiunta a quella standard, come suggerisce Peter. Le classi di proprietà nella libreria AETycoon possono risultare utili, in particolare DerivedProperty.

+0

ho fatto finire scrivere uno script per normalizzare loro. Grazie per il puntatore alla libreria. – jasonmw

0

Questo thread è stato utile e mi fa venir voglia di contribuire con un approccio simile per rendere possibile la ricerca di corrispondenze parziali. Aggiungo un altro campo sul tipo di archivio dati e salviamo ogni parola su una frase normalizzata come un set e poi uso il filtro IN per scontrare. Questo è un esempio con un Clojure. Normalizzare parte dovrebbe facile tradurre in java almeno (grazie alla @raek su #clojure), mentre l'interazione del database dovrebbe essere convertibile in qualsiasi lingua:

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