Context
My app uses a similar functionality like Tinder:
- Get nearest users (geohash filter + some others)
 - User can like/dislike users
 - On subsequent launches, user needs to see NEW users, without those he or she already liked/disliked
 
Current structure looks like this:

This is my code so far:
UserRepository:
  // Geohashing with GeoFlutterFire2
  Stream<List<DocumentSnapshot>> getAllUsersInRadius(
      {required LocationData currentLocation, required double radius}) {
    String field = 'position';
    GeoFirePoint centerPoint = _geo.point(
        latitude: currentLocation.latitude ?? 0.0,
        longitude: currentLocation.longitude ?? 0.0);
    return _geo
        .collection(collectionRef: _buildUserQuery())
        .withinAsSingleStreamSubscription(
            center: centerPoint, radius: radius, field: field);
  }
  // The query to pre-filter BEFORE the geohash query
  Query<Map<String, dynamic>> _buildUserQuery() {
    // Filter by 1. location (above), 2. isActive, 3. game list, 4. user type
    var query = _firestoreDB
        .collection(userCollection)
        .where("isActive", isEqualTo: true)
        .where("gameList", arrayContainsAny: ["Example1","Example2"])
        .where(Filter.or(Filter("userType", isEqualTo: currentUser.lookingFor[0]),
            Filter("userType", isEqualTo: currentUser.lookingFor[1])));
    return query;
  }
  // UserRelations = list of liked/disliked other users
  Future<List<String>> getUserRelationIDs(String userID) async {
    List<String> result = [];
    await _firestoreDB
        .collection(userCollection)
        .doc(userID)
        .collection("user_relations")
        .get()
        .then((querySnapshot) {
      for (var doc in querySnapshot.docs) {
        final otherUserID = doc.data()["otherUserID"];
        result.add(otherUserID);
      }
    });
    return result;
  }
UserViewModel:
  Future<void> _getAllUsersInRadius() async {
    currentLocationValue = await _userRepo.getCurrentUserLocation();
    await _userRepo.getCurrentUser(_authRepo.user!.uid);
    if (currentLocationValue != null) {
      // Needed for later filtering
      final userRelationIDs =
          await _userRepo.getUserRelationIDs(_userRepo.currentUser!.uuid);
      var subcription = _userRepo
          .getAllUsersInRadius(
              currentLocation: currentLocationValue!, radius: 2000)
          .listen((documentList) {
        // First, filter out all users that were already liked/disliked by currentUser
        var filteredUserList = documentList.where((docSnapshot) {
          if (!docSnapshot.exists || docSnapshot.data() == null) return false;
          String uuid = docSnapshot.get("uuid");
          if (!userRelationIDs.contains(uuid)) return true;
          return false;
        });
        // Now turn all documents into user objects and publish the list
        allUsersList = filteredUserList
            .map((docSnapshot) => _createUserFromSnapshot(docSnapshot))
            .toList();
        _allUsersStreamcontroller.add(allUsersList);
      });
      subscriptions.add(subcription);
    }
  }
My Problem
I see the following points as problematic:
- It feels very inefficient to load all the users first and then possibly discard most of them -> wasted reads/month
 - Due to using a geo-query (GeoFlutterFire2), I am very limited in the other filters I can apply (no ranges or sorting, since that is already used for the geohash) -> so I don't have a lot of options on the query side
 
So what I am wondering is: is there a more performant/efficient way to go about this?
Maybe by structuring the data differently?