Many to many array of refs vs through collection

I’m working on modeling tags that can be applied to documents in a collection. This is a many tags to many documents model, and I see two ways:

  1. use a through collection with documents that hold refs pointing to either side of the relation.
  2. use an array of refs on the document that needs the tags.

There are some resources for the old FQLv4 version of the language that talk about some of the tradeoffs, like this blog post: Getting started with FQL, Fauna’s native query language - part 3

Is there similar information that talks about these same things in the context of FQLv10?

2 Likes

The content of the article is still applicable, though all of the FQL is v4.

Both techniques – using a link table, or an array of refs – are still valid in v10.

One thing that stands out to me that would be different is how v10 handles Multi-valued Attributes (MVAs). In v4 indexes, all terms and values that are arrays are treated as MVAs. In v10, you have to specify it explicitly. There’s a huge benefit in here, which allows you to specify the array as an MVA term, but use the whole array as a value.

// FSL
collection MyCollection {
  history_days 0

  index by_tag__created_at_asc {
    terms [mva(.tags)]
    values [.created_at, .tags]
  }
}

I don’t really understand the difference between MVA and not MVA in this instance. Would you be able to elaborate further?

A fair question!

The short answer is that without an MVA (default for v10), the field is handled like a single scalar value. With an MVA, an index entry is created for each item in the array.

Consider the following Collection, with two indexes on it. One indexes on the field .tags and another indexes on the field .tags as a MVA.

collection Tagged {
  history_days 0

  index by_tags {
    terms [.tags]
  }

  index by_tag {
    terms [mva(.tags)]
  }
}

and let’s create some examples

Tagged.create({
  tags: ["canine", "boxer", "medium"]
})

Tagged.create({
  tags: ["canine", "Rotweiler", "large"]
})

For the index that has a “regular” term, it will use the entire array like a scalar value. You need to provide the whole thing to match on it.

image

Note that since the array is handled verbatim, so the items must be in order

image

We can use the MVA index to look up docs by a single tag

image

And why is returning a non-mva term that significant of a benefit? Forgive me because I haven’t dealt with arrays in v4.

It was needed some folks. I think that defining index values as non-MVA is more significant, but there are some times that it’s desired for terms, too.

Okay, switching gears: Your example has a “tags” array for each item in the collection. I’m looking to do something similar, but each tag has some semantic meaning to the application and would have to be pre-configured by the group admin. To support this and easily changing tag names, in case of a typo or something else, I was looking to model the tags as their own collection.

In your example, this would mean storing the tags as an array of refs instead of an array of strings. Is it possible to index an array of refs to achieve a by_tag syntax? This would require the index somehow dereferencing the ref to get the name field of the referenced tag.

I didnt find any discussion of mva in the documentation. Seems like it would be helpful if it were mentioned?