66

I have the following structure on my Firebase database: firebase database

I would like to search for a user by name, last name or email but as I don't have the user key in the level above I don't know how I can achieve this. I'm doing and administrator session so it wouldn't have access to the user key.

I have tried:

let usersRef = firebase.database().ref('users');
usersRef.orderByValue().on("value", function(snapshot) {
    console.log(snapshot.val());
    snapshot.forEach(function(data) {
        console.log(data.key);
    });
});

But it brings all the users on the database. Any ideas?

starball
  • 20,030
  • 7
  • 43
  • 238
Barbara Brina
  • 663
  • 1
  • 5
  • 5

3 Answers3

103

You can use equalTo() to find any child by value. In your case by name:

ref.child('users').orderByChild('name').equalTo('John Doe').on("value", function(snapshot) {
    console.log(snapshot.val());
    snapshot.forEach(function(data) {
        console.log(data.key);
    });
});

The purpose of orderByChild() is to define the field you want to filter/search for. equalTo() can get an string, int and boolean value.

Also can be used with auto generated keys (pushKey) too.

You can find all the documentation here

Gerard Cuadras
  • 1,655
  • 1
  • 17
  • 23
  • Is this possible to accomplish as an auto-complete system? Like, if a user types 'John' can you call orderByChild based on relevance? – Nathan Bird Dec 23 '17 at 19:12
  • @Epicality you can use `startAt()` to do something like you are mentioning. [Here](https://firebase.google.com/docs/database/web/lists-of-data#filtering_data) you can find all the documentation. But basically search as `equalTo()` but only checks if the string starts with users typing. – Gerard Cuadras Jan 03 '18 at 11:00
  • How can I get nodes which have two fields wth boolean values: which first field or second is `true`? – Konstantin Konopko Jan 19 '18 at 18:00
  • @KonstantinKonopko check the [documentation](https://firebase.google.com/docs/reference/js/firebase.database.Query#equalTo). You can use `equalTo()` with number, string, boolean or null. So just replace my answer with ... `orderByChild('name').equalTo(true)`... – Gerard Cuadras Mar 07 '18 at 01:26
  • orderByChild only orders by direct child not "grand-child". So, how would this work if the users-node direct child is a pushKey or id-string of some sort. According to the docs ref.child('users').orderByChild('name') will fail because there is no child of the users node that equals "name". They are all id strings. I'd love to be wrong here. Perhaps this could work if you were using orderByChild with child_added instead of value? – Joshua Dyck Mar 21 '18 at 02:16
  • @JoshuaDyck could you create a new question ? Post what you expect and an example of your data and I will check it. Thanks! – Gerard Cuadras Jun 01 '18 at 14:00
  • 1
    I figured it out. I was reading some misinformation due to outdated stack overflow material. OrderByChild worked as per your answer. – Joshua Dyck Jun 01 '18 at 17:55
  • Out of curiosity, is it possible to do the filtering if the value of 'name' was an array of integers and I look for a specific value in it? Imagine every user has a name and the value of it looks like this: [1, 2, 3, 4] and I want to filter all the users who have '2' in their 'name' array. – user2128702 Nov 13 '18 at 07:17
10

A warning to avoid unpleasant surprises: when you use orderByChild and equalTo do not forget to add an index on your data (here's the doc)

If you don't all the nods will be downloaded and filtered client side which can become very expensive if your database grows.

Joan
  • 270
  • 3
  • 7
1

Heres the v9 version:

import { 
   getDatabase, ref, query, 
   orderByChild, get, equalTo,
} from "firebase/database";

const db = getDatabase();
const usersRef = query(ref(db, `users`), ...[orderByChild("name"), equalTo("John Doe")]);
const snapshot = await get(usersRef);
const data = snapshot.val();
Dustin Spengler
  • 5,478
  • 4
  • 28
  • 36