1

I want to use Firebase real-time database in my app project. I want to check if the word which is filled by user exists in database.

Here is my database ss:

enter image description here

Here is my code:

private Button button;
private FirebaseDatabase database;
private DatabaseReference mRef;
private TextView tvResult;
private EditText et1;

    et1=(EditText) findViewById(R.id.et1);
    button=(Button) findViewById(R.id.btn);
    tvResult=(TextView) findViewById(R.id.tvResult);
    database=FirebaseDatabase.getInstance();
    mRef=database.getReference();

  button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            city=et1.getText().toString();


            Query query = mRef.child("app").orderByChild("cities").equalTo(city);
            query.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    if (dataSnapshot.exists()) {
                        // dataSnapshot is the "issue" node with all children with id 0
                        String get= dataSnapshot.getValue().toString();
                        tvResult.setText(get);
                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {}
            });
        }
    });

As I said, user fills edittext and after clicking a button, I want to show written city in textview if there is in database.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Kemal Aydeniz
  • 119
  • 2
  • 10

2 Answers2

1

What you have in your cities is a set of values: a collection of values, where each value is unique, and the order doesn't matter. So it's a single property with multiple values. And while NoSQL databases are all about denormalizing the data, this is actually one of the cases where I'd recommend that you normalize it a bit.

In the Realtime Database you'll typically model a mathematical set as this JSON:

cities: {
  london: true,
  paris: true,
  milan: true,
  ny: true,
  istanbul: true
}

This data structure has the advantage that:

  1. Each city is by definition unique, since keys must be unique in their location. I.e. there's no way to have london in here twice.
  2. Each city is now stored as a separate property, which means you can query for it separately.

For example, if you have a list of say trips where each trip can have a cities node, and you model it as I've shown, you could query for all cities that include New York with:

firebase.database().ref("cities").orderByChild("cities/ny").equalTo(true)

This will technically work, but will perform pretty badly, because of the way Firebase Realtime Database indexes work. For more on that, and an explanation of how to model this to allow the use-case, have a look at my answer here: Firebase query if child of child contains a value.

I definitely recommend that you check Cloud Firestore out. This use-case is precisely one where Firestore recently released some big improvements. In Firestore you can now store your data set in an array:

["london", "paris", "milan", "ny", "istanbul"]

So say that again you have a collection of trips, and for each trip you have a field cities whose value is the array above. You can now query for trips that include New York with:

firebase.firestore().collection("trips").where("cities", "array-contains", "ny")

And unlike with the Realtime Database, on Firestore this query will scale very well. For more on this see the blog post Better Arrays in Cloud Firestore!.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • thank you frank. i will work with very large data, maybe thousands of cities. do you advice using firestore? – Kemal Aydeniz Sep 16 '18 at 09:21
  • Thousands is not a high number for either Realtime Database (as long as you create the additional data structure in my linked answer) or Firestore. But Firestore definitely has the better scalability properties between the two, as it scales horizontally. I.e. reading 10 trips will always take the same amount of time, no matter how many trips there are in the collection. – Frank van Puffelen Sep 16 '18 at 13:39
0

Unfortunately, there is no query in Firebase real-time database that looks something like this:

mRef.child("app").orderByChild("cities").contains(city)

But for small datasets, there is a workaround that can help you solve this, which is by querying the database to get all the value for your cities property and use contains() method like this:

String str1 = dataSnapshot.child("cities").getValue(String.class);
String str2 = "london";
boolean b = str1.toLowerCase().contains(str2.toLowerCase());

If you'll try to print the value of b, you'll see that is true. But the above examples works well enough only for very small datasets, it doesn't work for large datasets and this is because downloading an entire object to search for fields client-side isn't practical. In this case, I recommend use a third-party search service like Algolia.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • thank you very much. is there any solution of my problem in Firebase Cloud Firestore? – Kemal Aydeniz Sep 14 '18 at 12:50
  • No, there is not! Please see **[here](https://stackoverflow.com/questions/47115422/is-there-a-way-to-search-sub-string-at-firestore/47133345)** more details. Official documentation of Firestore provides the same solution. – Alex Mamo Sep 14 '18 at 12:52