使用 objectify 在实体中搜索子字符串

Posted

技术标签:

【中文标题】使用 objectify 在实体中搜索子字符串【英文标题】:Search for substring within an entity using objectify 【发布时间】:2011-10-24 06:54:10 【问题描述】:

我有一个名为 lastName 的实体,其值为“Benjamin”。如果用户输入“Ben”或“jam”或“Benja”,有没有办法客观化。我仍然可以使用 query.filter() 找到这个实体。我必须使用查询,因为我正在检查其他搜索条件。

我在“Obgaektify”中看到了一个名为“starts with”的运算符。但它不工作。任何建议,将不胜感激。谢谢

【问题讨论】:

为什么要在名称中进行子字符串搜索?我从来没有见过一个好的用例。 它实际上不在名称之内。它通常在文本搜索中。但为简单起见,我只是说名字:) 好吧,问题仍然存在。全文搜索会进行词干提取和规范化,然后搜索整个单词,因为查询 'cat' return 'defecate' 没有什么意义。 现在需求改变了,我只需要检查它是否以给定的文本开头。就像“benjamin”以“ben”而不是“jam”或其他任何东西开头。所以我会尝试下面发布的解决方案并查看结果。感谢您的帮助 【参考方案1】:

子字符串没有“LIKE”类型的查询,但是可以通过利用索引上的>< 运算符来模拟区分大小写“开头为”。

// The start string
String searchStr = "Ben";

// emulate a "starts with" query
Query q = new Query("MyEntity")
q.addFilter("name", Query.FilterOperator.GREATER_THAN_OR_EQUAL, searchStr);
q.addFilter("name", Query.FilterOperator.LESS_THAN, searchStr + "\ufffd");

查询将“搜索”name 属性以查找以“Ben”开头且小于 "Ben\ufffd" 的项目,其中 \ufffd 是可能的最高 unicode 字符。

【讨论】:

`u'\ufffd' 是此处使用的规范“最大 UTF 字符”。 Cool Shady,勾选绿色勾号接受答案,这会给你 2rep,代表答案所有者并向其他人表明问题已解决。【参考方案2】:

对于类似包含的查询没有标准的现有索引。顺便说一句,你总是可以介绍你自己的。在这种情况下,您可以这样做:

    添加和合成字段如String[] lastNameIndex 添加标记为@PrePersist 的方法,该方法将使用所有可用组合填充lastNameIndex 字段 当您想使用该索引查找实体时,请执行query.filter('lastNameIndex =', val)

【讨论】:

【参考方案3】:

将 Chris 的答案和 Nick 的评论放在一起,这是为 objectify V4 构建查询过滤器的代码:

public <T> Query<T> fieldStartsWith(Query<T> query, String field, String search)
    query = query.filter(field + " >=", search);
    return query.filter(field + " <", searchStr+"\ufffd");

【讨论】:

我认为应该是 &lt; "\ufffd" 而不是 &lt;= 因为 FFFD 不是可打印的 ascii 字符,因此您需要排除它。但在实践中,这可能并不重要。如果我错了,请纠正我。 谢谢奥利弗,你是对的。我修改了答案!【参考方案4】:

我使用了标记化方法。这是Java中的代码:

private String tokenize(String phrase) 
StringBuilder tokens = new StringBuilder();
try 
  for (String word : phrase.split(" ")) 
    if (word.length() < 1) 
      continue;
    
    int j = 1;
    while (true) 
      for (int i = 0; i < word.length() - j + 1; i++) 
        tokens.append(word.substring(i, i + j)).append(" ");
      
      if (j == word.length()) 
        break;
      
      j++;
    
  
 catch (Throwable t) 
  t.printStackTrace();

return tokens.toString();

这允许定义一个可索引的字段,然后处理标准的 Ofy 查询和 SearchService。

【讨论】:

以上是关于使用 objectify 在实体中搜索子字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何在数组键中搜索子字符串?

在 MariaDB 中搜索子字符串或单词

无法从 Ansible 变量中搜索子字符串

在字符串数组中搜索子字符串的最有效方法

在列表中的元素中搜索子字符串并删除该元素

哪种 C# 数据结构允许最有效地在一对字符串中搜索子字符串?