Indexing on embedded shapes and lists

I am a bit confused regarding the capabilities of (field) indexing, as the documentation only uses it in top-level scalar examples but the syntax suggests deeper addressing:

@createIndex(fields: [{ path: string[] }])

I’ll show two instances where I was confused by this directive, we can look at both from an example in the docs (slightly extended):

type EducationModuleA 
  @createModel(...)
  # ❌ Would assume we can use indexes to create a filter for a lists
  @createIndex(fields: [{ path: ["learner"] }])
{
  module_name: String!
  module_domain: String
  number_of_topics_covered: Int!
  usernames_enrolled: [String!]!
}

type EducationModuleB 
  @createModel(...)
  # ❌ Would assume we can use indexes in fields in deeper shapes
  @createIndex(fields: [{ path: ["learner", "username"] }])
{
  module_name: String!
  module_domain: String
  number_of_topics_covered: Int!
  learners_enrolled: Learner!
}

type Learner {
  first_name: String!
  last_name: String!
  username: String!
}

In A, the composite compiles but no filters are available for the property in GraphiQL.

In B, we get this error:

Error: Could not resolve learner.username as a valid path
    at applyIndexingToObjects...

In my actual use-case I wanted the model to contain a list of embedded shapes, but these two simpler cases demonstrate what I think is the limitation preventing this.

Am I extrapolating features from the syntax of the directive?
If so, are there plans to extend this indexing feature to capture any or all of the demonstrated cases?
Otherwise, I’m just happy to share my experience hitting an unexpected snag :slight_smile:

For your first example, it doesn’t look like your Model has a field named learner at all, so I assume that’s the problem?

The array syntax for specifying the index is so you can index fields in a nested JSON object. Like for example, if you had a profile object that looked like:

{ name: 'spencer',
  address: {
    street: 'main st'
    number: '100',
    state: "MA",
    country: "USA"
  }
}

You could define an index on the state that the user lives in using @createIndex(fields: [{ path: string['address', 'state'] }]).

Good call out that this isn’t shown in the docs anywhere. We should definitely get the docs updated with an example of how to use the ‘path’ field when defining indices on nested objects. @Justina @mzk @jpham.

Hmm, I just realized your example B is pretty much exactly what I described in my last post. I had thought Learner was a relation to another Model, which we wouldn’t expect to work, but it’s not, it’s an embedded type. That does seem like it should work. @paul could you take a look at this?

@spencer Regarding the incorrect field names it’s just a typo in the post and it’s too late to edit the post. I adapted the one from the wiki as a public example, but apparently I did so hastily. With the correct field names in the directives (learner => usernames_enrolled and learner => learners_enrolled, respectively) the errors I listed still apply. :slight_smile:

Indices can be defined on nested fields but query filters and ordering apply to scalar fields directly set on the model, embedded objects and lists are not supported.

Got it! What is the purpose of defining an index on a nested field if it cannot be used for filtering or ordering?