2

I need to add tags to documents in Firestore.

These tags are created by admin users, and each Tag is a document in a Tags collection.

One or more of these tags are then applied to other documents, say Item documents.

We then need to be able to query the Items for ones that contain a specific Tag id, and have other range filters - date created within a range, order by date created, user id matches a specific user etc.

How would I structure the Item tag data so it can be queried?

  • An Array property can't be queried, so that wont work.
  • A map or set must be pre indexed, which also won't work as its dynamic data.
  • If I had a pre-defined number of allowable tags, and save each as a property, tag1, tag2, tag3 etc, I could try to query that, but OR is not supported...

  • I could add another collection, that holds the one-to-many relationships

    • say ItemTags, that has {itemId, tagId}, and then Query that first to get a list of Item ids, but again, how do I then user that list of ids to filter the Items collection?

I don't want this client side as the data is going to be very large.

UPDATE: The Tags are hierarchical, and you can only have one tag at each level. So one possible option is to have top level fields on the Item: tag1, tag2, tag3 etc with a pre defined limit. Then when the Item is created, the correct tag levels are inserted, and when its queried, we would need to know which level tag the user is looking for and we could then query item.tag1 = levelOneTag AND item.tag2 = levelTwoTag.

Not ideal as it limits the level, but I'm pretty sure 10 would cover it.

Matt Bryson
  • 2,286
  • 2
  • 22
  • 42
  • In general with NoSQL databases, if your use-case can't be met with a certain data model, modify or augment the model so that it allows your use-case. When it comes to categorization of items, you'll often end up with a reverse "index": a collection where you can look up the items (or item IDs) for a specific category. Also see https://stackoverflow.com/a/41528908 and https://stackoverflow.com/a/40657455. While both were written for the realtime database, the principals apply to Cloud Firestore too. – Frank van Puffelen Jan 29 '18 at 14:44
  • I am currently looking at the exact same use case? Did you ever find a solution for this? – Dan Dec 11 '19 at 07:41
  • No, not really. In the end we just mapped the data client side, far from ideal, but was the most appropriate solution. – Matt Bryson Dec 12 '19 at 11:39

1 Answers1

2

What I would do is to have a subcollection on each tag, with all the document IDs that have that particular tag. And also a subcollection on each document that lists all the tags that that document has.

What I have found with NoSQL and Firestore lately is that it is very fast and scalable with the downsize that you need to spend more time on updates.

I usually do this with triggers with firebase functions. Like for example you could add a listener when a tag is added/modified/deleted into a document sub collection and you update or delete that document ID in that particular tag sub collection. (ID or any other field that you need to filter)

See https://firebase.google.com/docs/functions/firestore-events

That way you dont have that much client logic and you have everything in the backend which is easier to maintain.

sebastianf182
  • 9,844
  • 3
  • 34
  • 66