0

I have a collection/table that is structured like this:

{
  UsedPromos: {
    "userid_1": {
      "product_1_1": "promo_1_1",
      "product_1_2": "promo_1_2",
      ...
      "product_1_n": "promo_1_n",
    },
    "userid_2": {
      "product_2": "promo_2"
    },
    ...
    "userid_m": {
      ...
    }
  }
}

How can I query an exact match to some "promo_x_y"? I have tried this so far:

const admin = require("firebase-admin");
admin.initializeApp(...);
const ref = admin.database().ref("/UsedPromos");
ref.orderByValue()
  .equalTo("promo_x_y")
  .once("child_added")
  .then((snapshot) => {
    console.log(`{key: ${snapshot.key}, value: ${snapshot.val()}}`);
    return snapshot
  });

But it didn't return anything.

1 Answer 1

2

If you are looking for all products that are part of the promotion promo_x_y, you need to adjust your query one level deeper than what you are currently doing.

Currently you are comparing the values of user_1, user_2, and so on to the value "promo_x_y". You get no results, because no entry /UsedPromos/user_1 = "promo_x_y" exists.

/UsedPromosByUser/{user}/{product} = {promo} (your current structure)

To fix this, you will need to search an individual user's list of products. Using the below snippet will log each product that has a value of "promo_x_y".

const admin = require("firebase-admin");
admin.initializeApp(/* ... */);

const ref = admin.database().ref("/UsedPromos");
const userToSearch = "user_1";

ref.child(userToSearch)
  .orderByValue()
  .equalTo("promo_x_y")
  .once("child_added")
  .then((snapshot) => {
    // snapshot.val() will always be "promo_x_y", so don't bother logging it.
    console.log(`${snapshot.key} uses "promo_x_y"`);
    return snapshot;
  });

Depending on your use case, it may be better to use a "value" event instead.

const admin = require("firebase-admin");
admin.initializeApp(/* ... */);

const ref = admin.database().ref("/UsedPromos");
const userToSearch = "user_1";

ref.child(userToSearch)
  .orderByValue()
  .equalTo("promo_x_y")
  .once("value")
  .then((querySnapshot) => {
    const productKeys = [];
    // productSnapshot.val() will always be "promo_x_y", so don't bother logging it.
    querySnapshot.forEach((productSnapshot) => productKeys.push(productSnapshot.key));
    
    console.log(`The following products have a value of "promo_x_y" for user "${userToSearch}": ${productKeys.join(", "}`);
    return productKeys;
  });

If you are looking to find all products, across all users, that use "promo_x_y", you should create an index in your database instead of using a query.

/UsedPromosByPromo/{promo}/{user}/{product} = true
OR
/UsedPromosByPromo/{promo}/{product}/{user} = true

Instead of using true in the above structure, you could store a timestamp (time of purchase, time promo expires, etc)

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

1 Comment

Yeah, the 3rd that you mentioned is the one I'm looking for. I need to find the user who has that promotion, so I need to find across all users. In the event that I set the index, what would the index look like in the rules and how to read from that?

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.