英文:
Search entries in Go GAE datastore using partial string as a filter
问题
我在数据存储中有一组条目,我想在用户输入查询时进行搜索/检索。如果我有完整的字符串,那很容易:
q := datastore.NewQuery("Products").Filter("Name =", name).Limit(20)
但是我不知道如何处理部分字符串,请帮忙。
英文:
I have a set of entries in the datastore and I would like to search/retrieve them as user types query. If I have full string it's easy:
q := datastore.NewQuery("Products").Filter("Name =", name).Limit(20)
but I have no idea how to do it with partial string, please help.
答案1
得分: 4
q := datastore.NewQuery("Products").Filter("Name >", name).Limit(20)
在App Engine上没有like
操作,但是可以使用<
和>
代替。
例如:
'moguz' > 'moguzalp'
英文:
q := datastore.NewQuery("Products").Filter("Name >", name).Limit(20)
There is no like
operation on app engine but instead you can use '<' and '>'
example:
'moguz' > 'moguzalp'
答案2
得分: 1
这样的操作在AppEngine数据存储中不直接支持,所以您需要自己编写功能来满足这个需求。下面是一个快速的、脑海中可能的解决方案:
class StringIndex(db.Model):
matches = db.StringListProperty()
@classmethod
def GetMatchesFor(cls, query):
found_index = cls.get_by_key_name(query[:3])
if found_index is not None:
if query in found_index.matches:
# 由于我们只查询前几个字符,所以我们必须遍历结果集以找到所有与查询匹配的字符串。我们保持列表排序,所以这不难。
all_matches = []
looking_at = found_index.matches.index(query)
matches_len = len(foundIndex.matches)
while start_at < matches_len and found_index.matches[looking_at].startswith(query):
all_matches.append(found_index.matches[looking_at])
looking_at += 1
return all_matches
return None
@classmethod
def AddMatch(cls, match):
# 我们只索引前3个字符
index_key = match[:3]
index = cls.get_or_insert(index_key, list(match))
if match not in index.matches:
# 索引实体不是新创建的,所以我们需要添加匹配项并保存实体。
index.matches.append(match).sort()
index.put()
要使用这个模型,您需要在每次添加一个可能被搜索的实体时调用AddMatch方法。在您的示例中,您有一个Product
模型,用户将在其Name
上进行搜索。在您的Product
类中,您可能有一个AddNewProduct
方法,用于创建一个新实体并将其放入数据存储中。您将在该方法中添加StringIndex.AddMatch(new_product_name)
。
然后,在从您的AJAX搜索框调用的请求处理程序中,您将使用StringIndex.GetMatchesFor(name)
来查看以name
开头的所有存储产品,并将这些值作为JSON或其他格式返回。
代码内部发生的是,名称的前三个字符用作包含以这三个字符开头的所有存储名称的实体的key_name。使用三个字符(而不是其他数字)是完全任意的。正确的数字取决于您正在索引的数据量。StringListProperty中可以存储的字符串数量是有限的,但您还希望平衡存储在数据存储中的StringIndex实体的数量。进行一些数学计算可以得出一个合理的字符数量。
英文:
EDIT: GAH! I just realized that your question is Go-specific. My code below is for Python. Apologies. I'm also familiar with the Go runtime, and I can work on translating to Python to Go later on. However, if the principles described are enough to get you moving in the right direction, let me know and I wont' bother.
Such an operation is not directly supported on the AppEngine datastore, so you'll have to roll your own functionality to meet this need. Here's a quick, off-the-top-of-my-head possible solution:
class StringIndex(db.Model):
matches = db.StringListProperty()
@classmathod
def GetMatchesFor(cls, query):
found_index = cls.get_by_key_name(query[:3])
if found_index is not None:
if query in found_index.matches:
# Since we only query on the first the characters,
# we have to roll through the result set to find all
# of the strings that matach query. We keep the
# list sorted, so this is not hard.
all_matches = []
looking_at = found_index.matches.index(query)
matches_len = len(foundIndex.matches)
while start_at < matches_len and found_index.matches[looking_at].startswith(query):
all_matches.append(found_index.matches[looking_at])
looking_at += 1
return all_matches
return None
@classmethod
def AddMatch(cls, match) {
# We index off of the first 3 characters only
index_key = match[:3]
index = cls.get_or_insert(index_key, list(match))
if match not in index.matches:
# The index entity was not newly created, so
# we will have to add the match and save the entity.
index.matches.append(match).sort()
index.put()
To use this model, you would need to call the AddMatch method every time that you add an entity that would potentially be searched on. In your example, you have a Product
model and users will be searching on it's Name
. In your Product
class, you might have a method AddNewProduct
that creates a new entity and puts it into the datastore. You would add to that method StringIndex.AddMatch(new_product_name)
.
Then, in your request handler that gets called from your AJAXy search box, you would use StringIndex.GetMatchesFor(name)
to see all of the stored products that begin with the string in name
, and you return those values as JSON or whatever.
What's happening inside the code is that the first three characters of the name are used for the key_name of an entity that contains a list of strings, all of the stored names that begin with those three characters. Using three (as opposed to some other number) is absolutely arbitrary. The correct number for your system is dependent on the amount of data that you are indexing. There is a limit to the number of strings that can be stored in a StringListProperty, but you also want to balance the number of StringIndex entities that are in your datastore. A little bit of math with give you a reasonable number of characters to work with.
答案3
得分: 0
如果关键词的数量有限,您可以考虑添加一个部分搜索字符串的索引列表属性。
请注意,每个实体的索引数量限制为5000个,并且总实体大小限制为1MB。
但是,您也可以等待Cloud SQL和全文搜索API适用于Go运行时。
英文:
If the number of keywords is limited you could consider adding an indexed list property of partial search strings.
Note that you are limited to 5000 indexes per entity, and 1MB for the total entity size.
But you could also wait for Cloud SQL and Full Text Search API to be avaiable for the Go runtime.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论