Search code examples
faunadb

How to query on ref in Faunadb?


I have data like this

{
  "ref": Ref(Collection("categories"), "1"),
  "data": {
    "title": "Game"
  }
}

And

[
{
  "ref": Ref(Collection("courses"), "1"),
  "data": {
    "categoryRef": Ref(Collection("categories"), "1"),
    "courseTitle": "101",
    "description": "Some1"
  }
},
{
  "ref": Ref(Collection("courses"), "2"),
  "data": {
    "categoryRef": Ref(Collection("categories"), "1"),
    "courseTitle": "102",
    "description": "Some2"
  }
},
{
  "ref": Ref(Collection("courses"), "3"),
  "data": {
    "categoryRef": Ref(Collection("categories"), "2"),
    "courseTitle": "103",
    "description": "Some3"
  }
}
]

I just want to get all courses that belong to the selected category, in this case game

So result will be these.

[
    {
      "ref": Ref(Collection("courses"), "1"),
      "data": {
        "categoryRef": Ref(Collection("categories"), "1"),
        "courseTitle": "101",
        "description": "Some1"
      }
    },
    {
      "ref": Ref(Collection("courses"), "2"),
      "data": {
        "categoryRef": Ref(Collection("categories"), "1"),
        "courseTitle": "102",
        "description": "Some2"
      }
    }
]

Is this just a simple index on categoryRef and search in it? should I pass ref as FQL like this? q.Ref(q.Collection('categories'), '1')

Or maybe something like this which I don't know how to finish it.

q.Map(
    q.Paginate(q.Documents(q.Collection('courses'))),
    q.Lambda('courseDoc',
        q.Let({
            course: q.Get(q.Var('courseDoc')),
            categoryRef: q.Get(q.Select(['data', 'categoryRef'], q.Var('course'))),

Solution

  • You need an index to perform searching on collections of arbitrary size. Only small collections are amenable to the "table scan" approach.

    If create an index, like this:

    > CreateIndex({
      name: "courses_by_category",
      source: Collection("courses"),
      terms: [
        { field: ["data", "categoryRef"] },
      ],
    })
    

    Then you can search for course documents with a query like this:

    > Paginate(
      Match(
        Index("courses_by_category"),
        Ref(Collection("categories"), "1")
      )
    )
    {
      data: [ Ref(Collection("courses"), "1"), Ref(Collection("courses"), "2") ]
    }
    

    To fetch the entire document for matching entries:

    > Map(
      Paginate(
        Match(
          Index("courses_by_category"),
          Ref(Collection("categories"), "1")
        )
      ),
      Lambda("ref", Get(Var("ref")))
    )
    {
      data: [
        {
          ref: Ref(Collection("courses"), "1"),
          ts: 1663619044380000,
          data: {
            categoryRef: Ref(Collection("categories"), "1"),
            courseTitle: '101',
            description: 'Some1'
          }
        },
        {
          ref: Ref(Collection("courses"), "2"),
          ts: 1663619067090000,
          data: {
            categoryRef: Ref(Collection("categories"), "1"),
            courseTitle: '102',
            description: 'Some2'
          }
        }
      ]
    }