我正在开发一个用于管理客户的 Web 应用程序。所以我有一个客户实体,它由常见的字段组成,例如名字、姓氏、年龄等。
我有一个页面,这些客户显示为表格。在同一页面中,我有一个搜索字段,我想在用户使用 Ajax 在搜索字段中键入内容时过滤客户并更新表格。这是它应该如何工作的:
图 1:显示所有客户的主页:
图 2:只要用户输入字母“b”,表格就会更新结果:
鉴于 GAE 不支持部分文本匹配,我已经根据此处显示的内容欺骗并实施了它:TL;DR:我创建了一个客户索引,其中包含每个客户的搜索文档(doc_id=customer_key)。每个搜索文档都包含我希望能够搜索的每个客户字段的Atom 字段(例如:first_name,last_name):每个字段都是这样组成的:假设 last_name 是 Berlusconi,该字段将由这些组成原子字段“b”“be”“ber”“berl”“berlu”“berlus”“berlusc”“berlusco”“berluscon”“berlusconi”. 通过这种方式,我能够以类似于部分文本匹配的方式执行全文匹配。如果我搜索“Be”,则返回 Berlusconi 客户。
搜索是通过 Ajax 调用进行的:每当用户在搜索字段中键入内容时(ajax 会稍微延迟以查看用户是否继续输入,以避免发送大量请求),使用查询字符串进行 Ajax 调用,并返回一个 json 对象。
现在,调试中一切正常,但我在数据存储区中与几个人一起测试它。只要我放了很多人,搜索看起来很慢。
这就是我创建搜索文档的方式。每次将新客户放入数据存储时都会调用此方法。
def put_search_document(cls, key):
"""
Called by _post_put_hook in BaseModel
"""
model = key.get()
_fields = []
if model:
_fields.append(search.AtomField(name="empty", value=""),) # to 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 with doc_id=key.urlsafe()
doc_id=key.urlsafe(),
fields=_fields)
index = search.Index(name=cls._get_kind()+"Index") # not in try-except: defer will catch and retry.
index.put(document)
@staticmethod
def tokenize1(string):
s = ""
for i in range(len(string)):
if i > 0:
s = s + " " + string[0:i+1]
else:
s = string[0:i+1]
return s
这是搜索代码:
@staticmethod
def search(ndb_model, query_phrase):
# TODO: search returns a limited number of results(20 by default)
# (See Search Results at 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 = []
for 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
其他人有我同样的经历吗?如果是这样,您是如何解决的?
非常感谢你们,马可·加拉西
编辑:姓名、电子邮件、电话显然是完全发明的。 Edit2:我现在已经搬到 TextField,看起来快一点,但问题仍然存在