部分匹配 GAE 搜索 API

Posted

技术标签:

【中文标题】部分匹配 GAE 搜索 API【英文标题】:Partial matching GAE search API 【发布时间】:2012-10-05 15:08:51 【问题描述】:

使用GAE search API 是否可以搜索部分匹配?

我正在尝试创建自动完成功能,其中该术语将是一个部分单词。例如。

> b > 布伊 > 构建

都会返回“建筑”。

GAE 怎么可能做到这一点?

【问题讨论】:

【参考方案1】:

如Full Text Search and LIKE statement 所述,不,这是不可能的,因为搜索 API 实现了全文索引。

希望这会有所帮助!

【讨论】:

【参考方案2】:

虽然全文搜索不支持 LIKE 语句(部分匹配),但您可以绕过它。

首先,为所有可能的子字符串(hello = h、he、hel、lo 等)标记数据字符串

def tokenize_autocomplete(phrase):
    a = []
    for word in phrase.split():
        j = 1
        while True:
            for i in range(len(word) - j + 1):
                a.append(word[i:i + j])
            if j == len(word):
                break
            j += 1
    return a

使用标记化字符串构建索引 + 文档(搜索 API)

index = search.Index(name='item_autocomplete')
for item in items:  # item = ndb.model
    name = ','.join(tokenize_autocomplete(item.name))
    document = search.Document(
        doc_id=item.key.urlsafe(),
        fields=[search.TextField(name='name', value=name)])
    index.put(document)

执行搜索,然后哇!

results = search.Index(name="item_autocomplete").search("name:elo")

https://code.luasoftware.com/tutorials/google-app-engine/partial-search-on-gae-with-search-api/

【讨论】:

这很好用。我设法修改了 Ferris 的 search.index 函数以自动标记所有文本字段(换行),并且它“正常工作”。只是不要尝试直接从搜索结果中向用户显示该字段;) 我还添加了name.lower(),因为我在俄语方面遇到了一些奇怪的问题:如果标记以大写字母开头,我无法找到这样的标记。 友情提示:这句话是“瞧!” 我添加了限制子字符串长度的选项,以避免搜索文档增加过多的情况。 gist.github.com/AniX/33dddf2a1993ca941692【参考方案3】:

我对预先输入的控制有同样的问题,我的解决方案是将字符串解析为小部分:

name='hello world'
name_search = ' '.join([name[:i] for i in xrange(2, len(name)+1)])
print name_search;
# -> he hel hell hello hello  hello w hello wo hello wor hello worl hello world

希望有帮助

【讨论】:

【参考方案4】:

就像@Desmond Lua 的答案,但具有不同的标记化功能:

def 标记化(单词): 令牌=[] 单词 = word.split(' ') 言归正传: 对于我在范围内(len(word)): 如果 i==0:继续 w = 单词[i] 如果我==1: 记号+=[字[0]+w] 继续 令牌+=[令牌[-1:][0]+w] 返回 ",".join(token)

它将hello world 解析为he,hel,hell,hello,wo,wor,worl,world

它适用于轻型自动完成目的

【讨论】:

【参考方案5】:

我的版本优化:不重复标记

def tokenization(text):
    a = []
    min = 3
    words = text.split()
    for word in words:
        if len(word) > min:
            for i in range(min, len(word)):
                token = word[0:i]
                if token not in a:
                    a.append(token)
    return a

【讨论】:

请添加更多关于您发布的答案的描述先生。【参考方案6】:

在这里很晚才加入。

但这是我进行标记化的有据可查的函数。文档字符串应该可以帮助您很好地理解并使用它。祝你好运!!!

def tokenize(string_to_tokenize, token_min_length=2):
  """Tokenizes a given string.

  Note: If a word in the string to tokenize is less then
  the minimum length of the token, then the word is added to the list
  of tokens and skipped from further processing.
  Avoids duplicate tokens by using a set to save the tokens.
  Example usage:
    tokens = tokenize('pack my box', 3)

  Args:
    string_to_tokenize: str, the string we need to tokenize.
    Example: 'pack my box'.
    min_length: int, the minimum length we want for a token.
    Example: 3.

  Returns:
    set, containng the tokenized strings. Example: set(['box', 'pac', 'my',
    'pack'])
  """
  tokens = set()
  token_min_length = token_min_length or 1
  for word in string_to_tokenize.split(' '):
    if len(word) <= token_min_length:
      tokens.add(word)
    else:
      for i in range(token_min_length, len(word) + 1):
        tokens.add(word[:i])
  return tokens

【讨论】:

以上是关于部分匹配 GAE 搜索 API的主要内容,如果未能解决你的问题,请参考以下文章

GAE 搜索 API 排序

es深入搜索之部分匹配

ElasticSearch如何使用 ElasticSearch 搜索单词的一部分 模糊搜索 正则匹配 前缀匹配

autohotkey搜索部分匹配

Laravel 搜索数据库表以从查询中进行部分匹配

根据搜索值的部分匹配过滤多维数组