Shady Hussein
Shady Hussein

Reputation: 497

Search for substring within an entity using objectify

I have an entity called lastName with value "Benjamin". Is there a way in objectify that if the user put "Ben" or "jam" or "Benja". I still be able to find this entity using query.filter(). I must use the query as there are other search criteria iam checking.

I saw something in "Obgaektify" called "starts with" operator. but it isnot working. Any suggestions would be appreciated. Thanks

Upvotes: 10

Views: 3610

Answers (4)

Aram Paronikyan
Aram Paronikyan

Reputation: 1608

I have used the tokenization method. Here is the code in 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();}

This allows to define an indexable field, then process standard Ofy queries and SearchService.

Upvotes: 0

Zensursula
Zensursula

Reputation: 173

Putting the answer from Chris and the comment from Nick together, here is the code to build a query filter for 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");
}

Upvotes: 0

Chris Farmiloe
Chris Farmiloe

Reputation: 14175

There's no "LIKE" type queries for sub-string, however a case sensitive "starts with" could be simulated by taking advantage of the > and < operators on indexes.

// 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");

The query will 'search' the name property for items that begining with "Ben", and are less than "Ben\ufffd", where \ufffd is the highest possible unicode character.

Upvotes: 12

Igor Artamonov
Igor Artamonov

Reputation: 35961

There is no standard existing index for contains-like queries. Btw, you can always introduce your own. At this case you can do:

  1. add and synthetic field like String[] lastNameIndex
  2. add method marked as @PrePersist that will fill lastNameIndex field with all available combinations
  3. When you want to find entities using this index do query.filter('lastNameIndex =', val)

Upvotes: 2

Related Questions