Get documents from index matching value

I’m still confounded by what I think should be simple, and it’s holding me back.

Let’s say, I’ve got an index like this:

{
  name: "recipes_by_chef_id",
  unique: false,
  serialized: true,
  source: "Recipe",
  values: [
    {
      field: ["data", "chefId"]
    },
    {
      field: ["ref"]
    }
  ]
}

Where chefId is a unique UUID that comes from the app’s auth provider (Cognito).
The following query works, but it gets all of the documents, which I don’t want:

q.Map(
    q.Paginate(q.Match(q.Index("recipes_by_chef_id"))),
    q.Lambda(["chefId", "ref"], q.Get(q.Var("ref")))
)

I got this pattern from the docs here, right were it says: “The fix is easy. Copy the following query, paste it into the shell, and run it:”

What I want is to query the index and return all documents that match a specific chefId.

I got the following pattern from the very helpful (and patient) @ptpaterson, though I’ve yet to find this (arrow function) pattern documented. If that exists, please send me there!

q.Map(
    q.Filter(
        q.Paginate(q.Match(q.Index("recipes_by_chef_id"))),
        (chefId, ref) => q.Equals(chefId, searchChefId)
    ),
    (chefId, ref) => q.Get(ref)
)

For the record, searchChefId, is provided as a variable to the function running this query. I’ve even hard coded it, to test, and it still doesn’t work when I do that.

Weirdly, this pattern works for other queries on other indexes I’ve created, for example, with this index:

{
  name: "user_by_secret_code",
  unique: false,
  serialized: true,
  source: "User",
  values: [
    {
      field: ["data", "secretCode"]
    },
    {
      field: ["ref"]
    }
  ]
}

The following query works flawlessly:

q.Map(
    q.Filter(
        q.Paginate(q.Match(q.Index("user_by_secret_code"))),
        (secretCode, ref) => q.Equals(secretCode, searchCode)
    ),
    (secretCode, ref) => q.Get(ref)
)
);

searchCode, here, would be the same thing as searchChefId in the previous example.

Because the latter works and the former doesn’t I’m in a quandary. They seem practically identical to me.

Surely, I’m doing something wrong, but no matter how hard I scour the docs and Google, I haven’t the foggiest ideas on how to trouble shoot this.

Any help would be greatly appreciated.

Hi @Kimfucious!

The Index you defined has no terms, so it always returns the set that includes ALL recipes. It orders results by data.chefId, but it does not perform a match on that field. If you want the index to match a specific chef_id, then include that in terms rather than values.

You can define a different index like this

{
  name: "recipes_match_by_chef_id",
  unique: false,
  serialized: true,
  source: "Recipe",
  terms: [
    {
      field: ["data", "chefId"]
    }
  ]
}

and use it like this

q.Map(
    q.Paginate(q.Match(q.Index("recipes_match_by_chef_id"), searchChefId)),
    q.Lambda("ref", q.Get(q.Var("ref")))
)

You can check out our documentation on searching for exact matches.

A side note: naming-convention-wise, I might have named your current Index something more like all_recipes__checkId_asc. Names don’t actually effect anything. This is completely a matter of personal preference – cannot emphasize enough you’re not doing anything wrong. In any case, I have found it helpful to differentiate between an index that “matches by” a field vs “orders by” a field. Easier to combine them as well, for example recipes_by_tag__chefId_asc_title_dec could indicate to me that tag is a term and it’s ordered by chefId and then title in descending order.

I’ll hit this one real, fast, too. :smile: This is a convenience for the javascript driver. I saw that you were using the javascript driver (everything prefixed with q.) and used the arrow function form. The javascript driver can convert functions into FQL Lambda calls.

This is also just a personal preference. Honestly, I broke with my own best practice when I avoided Lambda FQL function here, so my apologies for that confusion.

2 Likes

Thanks again, @ptpaterson, for the insight.

So here’s something embarrassing: in my testing, I was using an incorrect value for the searchChefId. It was hardcoded in an environment variable, with a very sneaky typo.

Once I fixed that, the following query worked like the others that work, using that pattern.

q.Map(
    q.Filter(
        q.Paginate(q.Match(q.Index("recipes_by_chef_id"))),
        (chefId, ref) => q.Equals(chefId, searchChefId)
    ),
    (chefId, ref) => q.Get(ref)
)

The fact that I didn’t was totally baffling, and totally my fault :smiley:

I started using indexes with values only (no terms), as I got the impression that they were more performant than those with search terms, but I’m probably understanding that wrong, at least for certain scenarios.

In this scenario, I want to pull all recipes for a certain user, so I’m not sure I’m gaining anything by using an “values only” index over an index with a search term, as I’m only ultimately getting the ref of the recipes to get all of the values therein.

I appreciate the advice on naming conventions. I already have more indexes than I need, as I’ve been creating them as part of my learning curve, and now they’re all named wonky and hard to decipher what they do without looking into them.

Finally thanks for the clarification on how the Javascript driver converts functions into Lambdas. I’d scoured the docs and had not come across that usage.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.