Glad to hear it!
Anyway more information about automatic generation is available here

http://code.google.com/appengine/docs/java/datastore/queriesandindexes.html#Defining_Indexes_With_Configuration

BTW there's the answer to everything in that:

"Other forms of queries require their indexes to be specified in
datastore-indexes.xml, including:

    * queries with multiple sort orders
    * queries with a sort order on keys in descending order [.....]"

Your query seems to fall into the second case.

I think that in case of errors like the one you found you can simply
add the piece of XML to your datastore-indexes.xml.
Many times you're not so lucky to get the missing index statement, and
your queries simply return empty sets.

Regards
Lorenzo


On Jul 28, 12:37 pm, Miroslav Genov <mgenov.j...@gmail.com> wrote:
>   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...
> > 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-searchabl...
>
> >> 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�SimpleName());
> >>>>       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�Size));
> >>>>       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