Pipe a result to lambda

Something like:

Index:

CreateIndex({
  name: 'userByPost',
  source: Collection('posts'),
  terms: [
    { field: ['data', 'postRef'] }
  ],
  values: [
    { field: ['ref'] },
    { field: ['data', 'userRef'] }
  ]
})

It’s a 1-1 relationship between posts and users.

const result = fauna.query(
  q.Pipe(
    q.Match(
      q.Index('userByPost'),
      postRef
    ),
    q.Lambda(
      ['ref', 'userRef'],
      q.Get(q.Var('userRef'))
    )
  )
);

without Pipe, you would have to do:

const userByPost = await fauna.query(
  q.Get(
    q.Match(
      q.Index('userByPost'),
      postRef
    )
  )
);

const user = await fauna.query(q.Get(userByPost.data.userRef));

Another workaround that I found is:

const user = await fauna.query(
  q.Select(
    0,
    q.Map(
      q.Paginate(
        q.Match(
          q.Index('userByPost'),
          postRef
        )
      ),
      q.Lambda(
        ['ref', 'userRef'],
        q.Get(q.Var('userRef'))
      )
    )
  )
);

Since there is a one-to-one relationship, you should be able to avoid the Map.

const user = await fauna.query(
  q.Get(
    q.Get(q.Match(q.Index('userByPost'), postRef))
  )
)

Wrapping inside a Let might make it clearer!

const user = await fauna.query(
  q.Let(
    {
      userRef: q.Get(q.Match(q.Index('userByPost'), postRef))
    },
    q.Get(q.Var('userRef'))
  )
);
2 Likes

This gist has some example of getting nested data, i.e. ‘get some data, then get some more data’, which is basically what’s happening here… right?

The point for this Topic is just to provide some more FQL examples of ‘get data, then get more data’ so that the language starts to appear less foreign. It can be so verbose that when you look at it, surely you have done something wrong! Seeing some other gnarly looking FQL queries in the wild made me feel better about the direction I was going.

Cheers.

It worked with a little tweak! I had to do:

await fauna.query(
  q.Let(
    {
      result: q.Get(
        q.Match(
          q.Index('userByPost'),
          q.Ref(q.Collection('posts'), 'postId') // this is postRef
        )
      )
    },
    q.Get(
      q.Select(['data', 'userRef'], q.Var('result'))
    )
  )
);

Otherwise, I would get an error saying Ref or Set expected, Object provided., I figured it was because q.Get(q.Match(q.Index('userByPost'), postRef)) returns an Object, so I had to get the returnedValue.data.userRef and then I got the user.

1 Like