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

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

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

【问题讨论】:

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

标签: google-app-engine objectify


【解决方案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】:

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

  1. 添加和合成字段如String[] lastNameIndex
  2. 添加标记为@PrePersist 的方法,该方法将使用所有可用组合填充lastNameIndex 字段
  3. 当您想使用该索引查找实体时,请执行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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-21
      • 2013-11-09
      • 1970-01-01
      • 2017-03-11
      • 2019-10-06
      • 2018-07-11
      • 1970-01-01
      相关资源
      最近更新 更多