2

I am currently creating an app where the administrator should be able to tag images. The visitors can search for a tag, and see the images that have that tag.

One image can have more than one tag. This represents how I currently have set up my data:

Images: {
    PUSH_ID: {
        url: "https://cdn.filestackcontent.com/o0ze07FlQjabT9nuteaE",
        tags: {
            PUSH_ID: {
                tag: "1324"
            },
            PUSH_ID: {
                tag: "4321"
            }
        }
    }
}

When a visitor searches for a tag, I need to be able to query the tag, and find the URL of the images that have the given tag. I was thinking that something along the lines of this would work:

ref.orderByChild('tags/tag').equalTo(tag).once("value"...)

But after some reading I have come to the understanding that you can only query one level deep in Firebase.

If this is the case, I need to restructure my data, but I cannot figure out how it should be structured.

Can anyone help me?

Btw; I have been told that I should use something like Elasticsearch to query in Firebase, but this app is for an event with a limited ammount of traffic.

Thanks!

2 Answers 2

3

When modeling data in Firebase (and in most NoSQL databases), you need to model the data for how your app wants to use it.

For example:

Images: {
    PUSH_ID_1: {
        url: "https://cdn.filestackcontent.com/o0ze07FlQjabT9nuteaE",
        tags: {
            "tag1324": true,
            "tag4321": true
        }
    },
    PUSH_ID_2: {
        url: "https://cdn.filestackcontent.com/shjkds7e1ydhiu",
        tags: {
            "tag1324": true,
            "tag5678": true
        }
    }
},
TagsToImages: {
    "tag1324": {
        PUSH_ID_1: true,
        PUSH_ID_2: true
    },
    "tag4321": {
        PUSH_ID_1: true
    }
    "tag5678": {
        PUSH_ID_2: true
    }
}

I changed a few things from you model:

  1. I still store the tags for each image, so that you can show them when a user is watching a single image
  2. But now we store the tags in a "tag1234": true format, which prevents a image from being tagged with the same tag multiple times. Whenever you feel the need for an array that you want to do a contains() operation on, consider using this approach which is more akin to a set.
  3. I prefix the tag numbers with a static string, which prevents Firebase from trying to interpret the tag numbers as array indices.
  4. We now also store a map of tags-to-image-ids. In this map you can easily look up all image IDs for a specific tag and then load the images in a loop.

We've essentially duplicated some data (the tags are stored twice) to ensure that we can look the information up in two ways. If you have more ways you want to access the data, you may need to replicate even more. This is normal in NoSQL databases and is part of the reason they scale so well.

I highly recommend reading this article on NoSQL data modeling.

Sign up to request clarification or add additional context in comments.

4 Comments

This is a really good answer. Thanks Frank. When i want to show the tags on the image, i just remove the "tag" prefix client side, yes?
Also; say I wanted to delete an image. I would also want to delete the associated image tags. What query should i run on the "TagsToImages" object to find all the tags that have my image id?
Indeed: on the client, just convert the value back. You're just working around a quirky behavior in the Firebase client here. For getting all images with a tag, you'd ref.child('TagsToImages').child('tag'+tag_id').on('child_added'....
Awesome stuff. Thanks Frank!
2

And there is a Tags node in this structure like this, isnt it??

Tags: {
    "tag1324": {
        tagName: pets    
    },
    "tag4321": {
        tagName: daffodil
    }
    "tag5678": {
        tagName: tasmanian wolf
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.