python 2.7 - Partial Text Matching GAE -
i developing web application managing customers. have customer entity made usual fields such first_name, last_name, age etc.
i have page these customers shown table. in same page have search field, , i'd filter customers , update table while user typing in search field, using ajax. here how should work:
figure 1: main page showing of customers:
figure 2: long user types letter "b", table updated results:
given partial text matching not supported in gae, have tricked , implemented arising shown here: tl;dr: have created customers index, contains search document every customer(doc_id=customer_key). each search document contains atom fields every customer's field want able search on(eg: first_name, last_name): every field made this: suppose last_name berlusconi, field going made these atom fields "b" "be" "ber" "berl" "berlu" "berlus" "berlusc" "berlusco" "berluscon" "berlusconi". in way able perform full text matching in way resembles partial text matching. if search "be", berlusconi customer returned.
the search made ajax calls: whenever user types in search field(the ajax dalayed little bit see if user keeps typing, avoid sending burst of requests), ajax call made query string, , json object returned.
now, things working in debugging, testing few people in datastore. long put many people, search looks slow.
this how create search documents. called everytime new customer put datastore.
def put_search_document(cls, key): """ called _post_put_hook in basemodel """ model = key.get() _fields = [] if model: _fields.append(search.atomfield(name="empty", value=""),) # retrieve customers when no query string _fields.append(search.textfield(name="sort1", value=model.last_name.lower())) _fields.append(search.textfield(name="sort2", value=model.first_name.lower())) _fields.append(search.textfield(name="full_name", value=customer.tokenize1( model.first_name.lower()+" "+model.last_name.lower() )),) _fields.append(search.textfield(name="full_name_rev", value=customer.tokenize1( model.last_name.lower()+" "+model.first_name.lower() )),) # _fields.append(search.textfield(name="telephone", value=customer.tokenize1( # model.telephone.lower() # )),) # _fields.append(search.textfield(name="email", value=customer.tokenize1( # model.email.lower() # )),) document = search.document( # create new document doc_id=key.urlsafe() doc_id=key.urlsafe(), fields=_fields) index = search.index(name=cls._get_kind()+"index") # not in try-except: defer catch , retry. index.put(document) @staticmethod def tokenize1(string): s = "" in range(len(string)): if > 0: s = s + " " + string[0:i+1] else: s = string[0:i+1] return s
this search code:
@staticmethod def search(ndb_model, query_phrase): # todo: search returns limited number of results(20 default) # (see search results @ https://cloud.google.com/appengine/docs/python/search/#python_overview) sort1 = search.sortexpression(expression='sort1', direction=search.sortexpression.ascending, default_value="") sort2 = search.sortexpression(expression='sort2', direction=search.sortexpression.ascending, default_value="") sort_opt = search.sortoptions(expressions=[sort1, sort2]) results = search.index(name=ndb_model._get_kind() + "index").search( search.query( query_string=query_phrase, options=search.queryoptions( sort_options=sort_opt ) ) ) print "----------------" res_list = [] r in results: obj = ndb.key(urlsafe=r.doc_id).get() print obj.first_name + " "+obj.last_name res_list.append(obj) return res_list
did else had same experience? if so, how have solved it?
thank guys much, marco galassi
edit: names, email, phone totally invented. edit2: have moved textfield, little bit faster, problem still persist
Comments
Post a Comment