使用部分字符串作为过滤器在Go GAE数据存储中搜索条目。

huangapple go评论77阅读模式
英文:

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(&quot;Products&quot;).Filter(&quot;Name &gt;&quot;, 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 &lt; 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.

huangapple
  • 本文由 发表于 2012年2月17日 17:01:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/9325427.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定