3

My database structure is like this

What I want is to filter users from "uId", like Sqlite

SELECT * FROM users WHERE uId IN ('OTky08PtlIYDE4KHRIzvZxyqIKp1' ,  'UiHUd9BhpybDAmTiGTbgg30THPN2')

Is there any way from which we can directly get this kind of filter over firebase database?

IntelliJ Amiya
  • 74,896
  • 15
  • 165
  • 198
Maddy
  • 4,525
  • 4
  • 33
  • 53
  • 1
    Firebase doesn't have an equivalent for a SQL `SELECT * FROM table WHERE id IN (1,2,3)`. The performance increase over retrieving the items separately would be marginal at best, because Firebase already pipelines the requests over a single connection. See my answer here for a longer explanation: http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using-query-instead-of-obse/35932786#35932786 – Frank van Puffelen Mar 08 '17 at 14:23
  • @FrankvanPuffelen, thanks it works for me! – Maddy Mar 27 '17 at 06:30

2 Answers2

2

I had the exact similar problem retrieving users by IDs. I found that there was no way of making the IN query in Firebase.

David suggests in his video either denormalizing the database or making a query for every id.

I did not like denormalizing so I queried every user. If you're in to RxJava, here's what I did

@NonNull
private Observable<List<User>> userIdsToUsers(@NonNull final List<String> uids) {
    if (uids.isEmpty()) {
        return Observable.just(new ArrayList<>());
    }

    return Observable.combineLatest(userIdsToUserObservables(uids),
            new ListCastFunc<>(User.class));
}

@NonNull
private List<Observable<User>> userIdsToUserObservables(@NonNull final List<String> uids) {
    final List<Observable<User>> result = new ArrayList<>();
    for (final String uid : uids) {
        result.add(userIdToUserObservable(uid));
    }
    return result;
}

@NonNull
private Observable<User> userIdToUserObservable(@NonNull final String uid) {
    return RxFirebaseDatabase.observeValueEvent(getUsersReference().orderByKey().equalTo(uid))
            .flatMap(this::dataSnapshotToUserObservable);
}


@NonNull
private Observable<User> dataSnapshotToUserObservable(@NonNull final DataSnapshot ds) {
    return Observable.fromCallable(() -> dataSnapshotToUser(ds));
}

@Nullable
private static User dataSnapshotToUser(@NonNull DataSnapshot ds) {
    if (!ds.exists()) {
        return null;
    }

    return parsedObjHere;
}

private static final class ListCastFunc<T> implements FuncN<List<T>> {

    @NonNull
    private final Class<T> targetClass;

    ListCastFunc(@NonNull final Class<T> targetClass) {
        this.targetClass = targetClass;
    }

    @Override
    public List<T> call(final Object... args) {
        if (args == null || args.length == 0) {
            return new ArrayList<>();
        }
        final List<T> results = new ArrayList<>(args.length);
        for (final Object arg : args) {
            if (arg != null && targetClass.isAssignableFrom(arg.getClass())) {
                //noinspection unchecked
                results.add((T) arg);
            }
        }
        return results;
    }
}
Yaroslav Mytkalyk
  • 16,950
  • 10
  • 72
  • 99
  • Sorry but not in RxJava and already tired with denormalizing a database but I did not found that is a good idea! Is there any other way to implement this? – Maddy Mar 09 '17 at 06:37
  • @Malik just like I said, you can make a query for every uid and merge the results. That's what my answer does. – Yaroslav Mytkalyk Mar 09 '17 at 08:16
0
usersRef.orderByChild("uId").startAt("OTky08PtlIYDE4KHRIzvZxyqIKp1").endAt("UiHUd9BhpybDAmTiGTbgg30THPN2")
  • what if I have 10 users and need to filter users with 5 uIds? – Maddy Mar 08 '17 at 12:17
  • 2
    Oh, I misread your question, my bad. There's no way to search for multiple equalTo values. You'll just have to make multiple Firebase queries. Performance wise it doesn't matter much due to Firebase pipelining queries. –  Mar 08 '17 at 12:19
  • See http://stackoverflow.com/questions/29560088/firebase-equivalent-to-sql-where-in –  Mar 08 '17 at 12:27
  • I think this is Javascript solution, got the logic let me try with this. – Maddy Mar 08 '17 at 12:32
  • @PieterLaebens Please edit your answer with the feedback you gave on the comments so it's easier for everybody else to understand the solution :) – Marco Scabbiolo Mar 09 '17 at 04:34