0

I want to filter data in Firebase. I got some queries but I am unable to filter data as per my requirement.

Data :

{
  "messages": {
    "Data_1": {
      "Inner_3": {
        "Text": {
          "-Kqgd2_QSi5HIlyH6Om3": {
            "date": 1501840029764,
            "text": "hi"
          },
          "-Kqgd6zZf51AdKNPrsX8": {
            "date": 1501840047829,
            "text": "hello"
          }
        }
      }
    },
    "Data_2": {
      "Inner_2": {
        "Text": {
          "-Kqm5GijxFT54wZRHIJj": {
            "date": 1.501931572192E9,
            "text": "hi"
          },
          "-Kqm5YohOG1cFWO-WNGc": {
            "date": 1.501931646257E9,
            "text": "test"
          },
          "-Kqm6935IY8Ddj20Z3TN": {
            "date": 1.501931802871E9,
            "text": "new message"
          }
        }
      }
    }
  }
}

In above json, If I pass Inner_3 then It should return below result. It checks in all arrays if Inner_3 is available then give me main layer name with last TEXT from Inner_3.

{
  "messages": {
    "Data_1": {
      "Text": {
        "-Kqgd6zZf51AdKNPrsX8": {
          "date": 1501840047829,
          "text": "hello"
        }
      }
    }
  }
}

Please help me to achieve this result.

Jeeten Parmar
  • 5,568
  • 15
  • 62
  • 111

2 Answers2

1

Unfortunately that sort of query is not possible on the Firebase Database. You'll have to change your data structure to accommodate it.

One way is to add the Inner_3 as the value of a known property:

{
  "messages": {
    "Data_1": {
      "Key": "Inner_3"
      "Inner_3": {
        "Text": {
          "-Kqgd2_QSi5HIlyH6Om3": { "date": 1501840029764, "text": "hi" },
          "-Kqgd6zZf51AdKNPrsX8": { "date": 1501840047829, "text": "hello" }
        }
      }
    },
    "Data_2": {
      "Key": "Inner_2"
      "Inner_2": {
        "Text": {
          "-Kqm5GijxFT54wZRHIJj": { "date": 1.501931572192E9, "text": "hi" },
          "-Kqm5YohOG1cFWO-WNGc": { "date": 1.501931646257E9, "text": "test" },
          "-Kqm6935IY8Ddj20Z3TN": { "date": 1.501931802871E9, "text": "new message" }
        }
      }
    }
  }
}

Now you can query with:

ref.child("messages").orderByChild("Key").equalTo("Inner_3")

Alternatively you can add a separate lookup list:

"InnerToNodeNameMapping": {
  "Inner_3": "Data_1",
  "Inner_2": "Data_2"
}

Then you can find the path of the Inner_3 item by a direct lookup:

ref.child("InnerToNodeNameMapping").child("Inner_3")

And from that you can directly access the node (no query needed).

Having to adapt/expand your data structure to allow the use-cases that you want in your app is very common on Firebase and other NoSQL databases. Since you seem relatively new to NoSQL, I recommend reading NoSQL data modeling

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
0

You have to order by key .orderByKey(), and get the lastone, rember firebase pushed keys ar random strings that contain timestamp inside.

The most common ordering method is ref.orderByKey(). It orders the ref’s children by their keys, usually push keys — which order by time.

After you have your snapshot ordered by key you can do something like this:

var firstdata;
 snapshot.forEach(function(mySnapshot) {
  if (!firstdata) {
  firstdata = mySnapshot.val();
   }
  });
  console.log(firstdata);
Joaquin Peraza
  • 343
  • 1
  • 15
  • `.orderByKey()` is fine but main issue is to find 'Inner_3' from all upper layers. – Jeeten Parmar Aug 05 '17 at 12:50
  • 1
    I am already doing this. But what if I have 10000s of messages then I think it is not good option to fetch all data and filter it my side. – Jeeten Parmar Aug 05 '17 at 12:57
  • I understand, firebase is not thought to do that, the only workaround to do this is looping each elemnt and getting the last one, or storing the pushed keys in a path like /times and you retrieve from there the last key and the path where it store the text. – Joaquin Peraza Aug 05 '17 at 12:58