Reputation: 502
I am trying to query my (GAE Java) datastore's text field and expecting results including partial matches. For example, results for the search string "test" should include "test, test1, more tests, etc". Below is the Java code snippet I am using.
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Filter testFilter = new FilterPredicate("test", FilterOperator.GREATER_THAN_OR_EQUAL, testStr);
Query testQuery = new Query("testEntity").setFilter(testFilter);
List<Entity> testResults = datastore.prepare(testQuery).asList(FetchOptions.Builder.withLimit(100));
My test results are totally irrelavant. I am new to GAE and Java and I am sure I am not on the right track. I have searched for the right approach in SO and other sites and found solutions for Python, but couldn't find any for Java. The Java examples I came across are all using queries with integer values. Please suggest.
Upvotes: 2
Views: 2792
Reputation: 15477
My example is searching for users of my application by name. I created one document for each user, and that document contains every possible string that you can search for.
For example, the document for user "John Smith" has one string: search input delimited by spaces: "joh ohn smi smit mith (etc)".
Here the code I used to get this to work. The "id" is the id for the user in my backend datastore.
private void createSearchableUserDoc(String id, String displayName) {
List<String> substrings = buildAllSubstrings(displayName);
String combinedString = combine(substrings, " ");
// The input for this looks like "CHR CHRI CHRIS HRI HRIS" etc...
createUserDocument(id, combinedString);
}
private List<String> buildAllSubstrings(String displayName) {
List<String> substrings = new ArrayList<String>();
for (String word : displayName.split(" ")) {
int wordSize = 1;
while (true) {
for (int i = 0; i < word.length() - wordSize + 1; i++) {
substrings.add(word.substring(i, i + wordSize));
}
if (wordSize == word.length())
break;
wordSize++;
}
}
return substrings;
}
private String combine(List<String> strings, String glue) {
int k = strings.size();
if (k == 0)
return null;
StringBuilder out = new StringBuilder();
out.append(strings.get(0));
for (int x = 1; x < k; ++x)
out.append(glue).append(strings.get(x));
return out.toString();
}
private void createUserDocument(String id, String searchableSubstring) {
Builder docBuilder = Document
.newBuilder()
.setId(id)
.addField(
Field.newBuilder().setName("Display_Name")
.setText(searchableSubstring));
addDocToIndex(docBuilder.build());
}
private void addDocToIndex(Document document) {
Index index = getUserDocIndex();
try {
index.put(document);
} catch (PutException e) {
log.severe("Error putting document in index... trying again.");
if (StatusCode.TRANSIENT_ERROR.equals(e.getOperationResult().getCode())) {
index.put(document);
}
}
}
public static Index getUserDocIndex() {
IndexSpec indexSpec = IndexSpec.newBuilder().setName("USER_DOC_INDEX").build();
Index index = SearchServiceFactory.getSearchService().getIndex(indexSpec);
return index;
}
To perform a search I did this:
Query query = Query.newBuilder().build("Display_Name" + "=" + searchText);
Index userDocIndex = getUserDocIndex();
Results<ScoredDocument> matchingUsers = userDocIndex.search(query);
Upvotes: 3
Reputation: 2136
If you want to do the text search use , the GAE Full text search
https://developers.google.com/appengine/docs/java/search/
Upvotes: 2