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

时间:2011-08-10 16:52:36

标签: google-app-engine objectify

我有一个名为lastName的实体,其值为“Benjamin”。如果用户放“Ben”或“jam”或“Benja”,是否有一种客观化的方式。我仍然可以使用query.filter()找到这个实体。我必须使用该查询,因为我检查有其他搜索条件。

我在“Obgaektify”中看到一些名为“start with”运算符的东西。但它没有用。任何建议,将不胜感激。感谢

4 个答案:

答案 0 :(得分:12)

对于子字符串没有“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字符。

答案 1 :(得分:2)

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

  1. 添加String[] lastNameIndex
  2. 等合成字段
  3. 添加标记为@PrePersist的方法,该方法将lastNameIndex字段填入所有可用组合
  4. 如果要使用此索引查找实体,请执行query.filter('lastNameIndex =', val)

答案 2 :(得分:0)

将Chris的答案和Nick的评论放在一起,下面是构建对象V4的查询过滤器的代码:

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

答案 3 :(得分:0)

我使用了标记化方法。这是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。