First I wanna thank you all for the feedback.
Now I had looked into guestbook example at
http://code.google.com/p/guestbook-example-appengine-full-text-search/source/browse/trunk/guestbook/src/guestbook/SearchJanitor.java
and
I had modified my code to use the same query generation.
Here is a snippet of my method that is doing searching job.
http://pastebin.ca/1909986
For my badness it seems that the result is same as in my last post. When
I'm searching for a single word everything is working like a charm, but
when I type "my word" datastore is throwing
the following exception:
com.google.appengine.api.datastore.DatastoreNeedIndexException: no matching index found..<datastore-index
kind="DeviceAddressSearchIndex" ancestor="false" source="manual">
<property name="searchTerms" direction="asc"/>
<property name="searchTerms" direction="asc"/>
<property name="identifier" direction="desc"/>
</datastore-index>
Any idea how can I enable the automatic indexing ?
In fact, in other part in our project is using same technique with the
low level api and is working without any index definitions and etc. Here
are some snippets how we are doing it:
private List<Entity> getContractSearchIndexes(String query, String
searchIndex, int offset, int pageSize) {
timeLogger.start();
String searchString = query.toLowerCase().trim();
log.info("Search for: " + searchString);
String[] terms = searchString.split("\\s");
DatastoreService dataService =
DatastoreServiceFactory.getDatastoreService();
Query searchQuery = new Query("ContractSearchIndex");
for (String term : terms) {
searchQuery.addFilter(searchIndex, Query.FilterOperator.EQUAL, term);
}
List<Entity> indexes =
dataService.prepare(searchQuery).asList(FetchOptions.Builder.withOffset(offset).limit(pageSize));
timeLogger.resetAndLog("Search time");
return indexes;
}
The following code is working like a charm without any static index
definitions and etc. The only difference between both indexes is the
sorting order. In a few minutes I will try to remove it, so I can test
what will happens without any ordering.
On 28.7.2010 ?. 12:06 ?., l.denardo wrote:
Getting back to the original question, since the error appears to be
for the second query and it's only a get (no composite index),
probably it's only a matter of automatic indexing being disabled.
Just as a pointer on text search, there's a post here:
http://googleappengine.blogspot.com/2010/04/making-your-app-searchable-using-self.html
Regards
Lorenzo
On Jul 28, 1:33 am, Stephen Johnson<[email protected]> wrote:
Hi Miroslav,
Yes, I would say it is working on your local dev. because you have
automatic indexes enabled and so is automatically creating the
necessary index for you but then you are not deploying this
automatically generated index. It looks like your code splits search
phrases into individual words and applies an AND in you query filter
for each word, thus the search for "my word" becomes the filter:
searchTerms == 'my'&& searchTerms == 'word'
Thus, this requires a composite index consisting of searchTerms twice.
If you want to search for "my word" don't split it apart, just have
the filter have
searchTerms == 'my word'
I believe this should do the trick.
Stephen
On Jul 27, 3:06 am, Miroslav Genov<[email protected]> wrote:
Hello,
I'm encountering a strange issue with datastore list property indexes
when I'm trying to use them in a full-text search queries.
Here are my index definition, my model definitions, my sample code and
my test code, and the error that I'm getting when my app is deployed on
GAE.
Here is my searching index:
<datastore-index kind="DeviceAddressSearchIndex" ancestor="false"
source="manual">
<property name="searchTerms" direction="asc"/>
<property name="identifier" direction="desc"/>
</datastore-index>
Here are my model definitions:
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class DeviceAddressEntity {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
@Persistent
private String identifier;
....
....
@Persistent
private DeviceAddressSearchIndex searchIndex;
and my search index
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class DeviceAddressSearchIndex {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key id;
@Persistent
private Integer identifier;
@Persistent
private Date date;
@Persistent
private Set<String> searchTerms;
@Persistent(mappedBy = "searchIndex")
private DeviceAddressEntity address;
Here is body of my method that is executing the searching query:
public List<DeviceAddressEntity> findAllAddresses(Integer offset,
Integer pageSize, String searchQuery) {
String[] terms = {};
if (!Strings.empty(searchQuery)) {
String searchTerms = searchQuery.toLowerCase();
terms = searchTerms.split("\\s");
}
com.google.appengine.api.datastore.Query query = new
com.google.appengine.api.datastore.Query(DeviceAddressSearchIndex.class.get范impleName());
for (String term : terms) {
query.addFilter("searchTerms",
com.google.appengine.api.datastore.Query.FilterOperator.EQUAL,term);
}
query.setKeysOnly();
query.addSort("identifier",
com.google.appengine.api.datastore.Query.SortDirection.DESCENDING);
Set<Key> addressKeys = Sets.newHashSet();
PreparedQuery preparedQuery = datastoreService.prepare(query);
Iterable<Entity> addressEntities =
preparedQuery.asIterable(FetchOptions.Builder.withOffset(offset).limit(page范ize));
for (Entity entity : addressEntities) {
addressKeys.add(entity.getParent());
}
if (addressKeys.size() == 0) {
return Lists.newArrayList();
}
/** we are not using batches, cause mostly this search is for 5-10
elements max. */
List<DeviceAddressEntity> addresses = new
ArrayList<DeviceAddressEntity>(addressKeys.size());
for (Key key : addressKeys) {
DeviceAddressEntity address =
pm.get().getObjectById(DeviceAddressEntity.class,key);
addresses.add(address);
}
}
Here is my test that is testing how full text search is working
@Test
public void findAddressesUsingTextSearch() {
final DeviceAddressEntity first = DeviceAddressEntity.with("56",
NORMALIZED_MAC, "my first word", "33", "10", "11", "12", "13", "14");
final DeviceAddressEntity second = DeviceAddressEntity.with("57",
NORMALIZED_MAC, "my second word", "9", "10", "11", "12", "13", "14");
final DeviceAddressEntity third = DeviceAddressEntity.with("58",
NORMALIZED_MAC, "otherword", "9", "10", "11", "12", "13", "14");
MonitoringService service =
injector.getInstance(MonitoringService.class);
service.saveDeviceAddress("56", first);
service.saveDeviceAddress("57", second);
List<DeviceAddressEntity> addresses = service.findAllAddresses(0,
5, "my word");
assertEquals("text search is not working
correctly?",2,addresses.size());
}
and this test is passing
When app is deployed on GAE and when I type "my" in the search box, the
method is returning correct results, but when I type "my word" the
datastore is throwing the following exception:
com.google.appengine.api.datastore.DatastoreNeedIndexException: no
matching index found..<datastore-index kind="DeviceAddressSearchIndex"
ancestor="false" source="manual">
<property name="searchTerms" direction="asc"/>
<property name="searchTerms" direction="asc"/>
<property name="identifier" direction="desc"/>
</datastore-index>
Any idea what is causing this ?
--
You received this message because you are subscribed to the Google Groups "Google
App Engine for Java" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-appengine-java?hl=en.