Is this the best way to write those queries?

Hey there,
I just started using FaunaDB and I also started to write queries for different situations.

For example: I have a route /videos and anther route /videos/admin. My backend controller forwards the request to my video-service then queries the database. The difference between the admin-route and the non-admin route is that for the non-admin route only videos are returned that have a true-flag at isPublished.

My attempt is the following:

  1. Creating two indexes: get_all_published_videos_index and get_all_videos_index

  2. get_all_published_videos_index has the term data.isPublished and an empty value --> gives me the ref by default

  3. get_all_videos_index has both fields term and value empty

  4. Creating two functions: getAllPublishedVideosFn and getAllVideosFn

  5. The functions are called by the service with: fauna_client.query(q.Call(q.Function('getAllVideosFn'))) and
    fauna_client.query(q.Call(q.Function('getAllPublishedVideosFn'))) respectively

  6. getAllPublishedVideosFn looks like this:

     Query(
       Lambda(
         "",
         Select(
           "data",
           Map(
             Paginate(Match(Index("get_all_published_videos_index"), true)),
             Lambda(
               "videoRef",
               Let(
                 { videoDoc: Get(Var("videoRef")) },
                 {
                   id: Select(["ref", "id"], Var("videoDoc")),
                   title: Select(["data", "title"], Var("videoDoc")),
                   slug: Select(["data", "slug"], Var("videoDoc")),
                   urls: Select(["data", "urls"], Var("videoDoc")),
                   ...
                 }
               )
             )
           )
         )
       )
     )
    

Gives me back an array with all videos that have the isPublished: true flag

2.2) getAllVideosFn looks like this:

Query(
  Lambda(
    [],
    Select(
      "data",
      Map(
        Paginate(Match(Index("get_all_videos_index"))),
        Lambda(
          "videoRef",
          Let(
            { videoDoc: Get(Var("videoRef")) },
            {
              id: Select(["ref", "id"], Var("videoDoc")),
              title: Select(["data", "title"], Var("videoDoc")),
              urls: Select(["data", "urls"], Var("videoDoc")),
              ...
            }
          )
        )
      )
    )
  )
)

Gives me all videos back.

Questions: (1) Is this most efficient way and (2) are the queries supposed to be that explicit where I have to select every property I want fill with values manually?

Thanks a lot!

Hi @qhantom and welcome,

It very depends on how your documents look like and what you return from the indexes.
Would you send to me a doc sample and a full list of what you expect the index should return?
You can send me a private message if you prefer.

Luigi

Hi @qhantom,

You can write the query this way:

Map(
  Paginate(Match("refByPublished",false)),
  Lambda("videoRef",Select(['data'],Get(Var('videoRef'))))
)

and it returns an array of documents. This way you avoid the using of Let() and name field by field.

By creating an index like this:

CreateIndex(
  {
    name:'refByPublished',
    source:Collection("video"),
    terms:[{field:['data','isPublished']}]
  }
)

you don’t need a second index since you can query:

  • all published videos:
Paginate(
  Match('refByPublished',true)
)

*** all videos:

Paginate(
  Union(
    Match('refByPublished',true),
    Match('refByPublished',false)
  )
)

Hope this helps.

Luigi

This is awesome! Thanks a ton Luigi!

Another question: When I select the data property to retrieve my data, I get rid of the ref of the document. How can I add a property “ref” to my data response with the corresponding ref? And what do I do if I have a property that is a reference and I want to give it the reference-string not the whole reference object.
Example (course property should hold its reference only):

{
  id: 565346345345,
  title: 'My Video',
  course: 45657365753,
  isPublished: true
}

Hi @qhantom,

you may try this way:

Map(
  Paginate(Match("refByPublished",false)),
  Lambda("videoRef",Merge({ref:Var("videoRef")},Select(['data'],Get(Var('videoRef')))))
)

Luigi

Cool, and what if I want to populate a certain property like “course” with it’s it as I described above?

Hi @qhantom,

Sorry, I don’t get your point. Would you articulate a bit?

Luigi

Sure!
So, a video can have a property “course” and the value is a reference to an entity in my “courses” collection. If I query a video, it gives me the “course” property back but with all the stuff of information I do not need like:

"course": {
        "@ref": {
            "id": "281114314023514215",
            "collection": {
                "@ref": {
                    "id": "course",
                    "collection": {
                        "@ref": {
                            "id": "collections"
                        }
                    }
                }
            }
        }
    },

I only want to have the id as a value and not the whole object that is attached to it.

Hi @qhantom,

You can use Select() to pick up just the part you want to show.

Luigi