Yvonne Aburrow
Yvonne Aburrow

Reputation: 2728

NeedIndexError in Google App Engine, despite indexes being served

I have uploaded my index.yaml file using the command line SDK: adding index.yaml via command line

Unfortunately I now have some of my entities indexed twice (but they are all serving): enter image description here

But I am still getting a "Need Index Error" on running the page:

NeedIndexError: no matching index found. recommended index is:
- kind: RouteDetails
  ancestor: yes
  properties:
  - name: RouteName
    direction: desc

The suggested index for this query is:
- kind: RouteDetails
  ancestor: yes
  properties:
  - name: RouteName
    direction: desc

How can I get Google App Engine to recognise my entity's index?

And how do I delete the duplicates? (Do I need to?)

Upvotes: 0

Views: 105

Answers (3)

Yvonne Aburrow
Yvonne Aburrow

Reputation: 2728

Just in case anyone else stumbles across this question and is having a similar problem.

The reason it was looking for an index with ancestor: yes is that I was using the wrong query, and it should not have had an ancestor key in it at all.

Here is my new query:

class RouteDetails(ndb.Model):
    """Get list of routes from Datastore """
    RouteName = ndb.StringProperty()

    @classmethod
    def query_routes(cls):
        return cls.query().order(-cls.RouteName)


class RoutesPage(webapp2.RequestHandler):
    def get(self):
        adminLink = authenticate.get_adminlink()
        authMessage = authenticate.get_authmessage()
        self.output_routes(authMessage,adminLink)

    def output_routes(self,authMessage,adminLink):
        self.response.headers['Content-Type'] = 'text/html'
        html = templates.base
        html = html.replace('#title#', templates.routes_title)
        html = html.replace('#authmessage#', authMessage)
        html = html.replace('#adminlink#', adminLink)
        self.response.out.write(html + '<ul>')
        list_name = self.request.get('list_name')
        #version_key = ndb.Key("List of routes", list_name or "*notitle*")
        routes = RouteDetails.query_routes().fetch(20)

        for route in routes:
            self.response.out.write('<li>%s</li>' % route)
        self.response.out.write('</ul>' + templates.footer)

I was using this page of the documentation, which doesn't tell you how to construct a query for a kind with no ancestor.

https://cloud.google.com/appengine/docs/standard/python/datastore/queries

Upvotes: 0

Nick
Nick

Reputation: 1822

The index includes the order by direction - you can see the up arrows in the console view indicating all fields ascending.

The suggested index is a descending index on one of the properties.

Your 'duplicate' indexes have been introduced by the reason field, which you indexed as both capital r and lower case r, which are different named fields

Upvotes: 1

Tony P.
Tony P.

Reputation: 191

Datastore requires explicit indexes to be created for each query type when the query scans over more than one property or is an ancestor query. And kinds will certainly be indexed more than once if you have different query types.

For example:

SELECT * FROM RouteDetails
WHERE __key__ HAS ANCESTOR KEY(ParentKind, 'foo')
ORDER BY RouteName ASC

requires an ascending index.

- kind: RouteDetails
  ancestor: yes
  properties:
  - name: RouteName
    direction: asc

And

SELECT * FROM RouteDetails
WHERE __key__ HAS ANCESTOR KEY(ParentKind, 'foo')
ORDER BY RouteName DESC

requires a separate descending index.

- kind: RouteDetails
  ancestor: yes
  properties:
  - name: RouteName
    direction: desc

https://cloud.google.com/datastore/docs/concepts/indexes

In your case, it appears you are performing an ancestor query with a descending ORDER BY of the RouteName property and adding the suggested index to your index.yaml file should solve the problem for you.

As for the suspected "duplicates", which indexes need to exist depend on the specific queries your application performs.

But if you determine that you have extra unused indexes, the instructions for vacuuming indexes can be found here: https://cloud.google.com/datastore/docs/tools/indexconfig#Datastore_Deleting_unused_indexes

Upvotes: 1

Related Questions