It seems that the issue is with the sorting order. Now sorting order has been removed and works like a charm.

On 28.7.2010 ?. 13:22 ?., Miroslav Genov wrote:
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<onepagewo...@gmail.com>  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<mgenov.j...@gmail.com>  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 google-appengine-j...@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.

Reply via email to