Problem fetching users with similar username in firestore v9

51 Views Asked by At

I'm trying to filter users from firestore with a similar name or the first letter equals, like Instagram. Although my query doesn't seem to be working correctly, sometimes it returns the user with wrong name, for example. If I type Geov it returns users with J and N
Like this:

enter image description here

But sometimes it returns half right, like this:

enter image description here

This is my logic:

export async function searchUsers(searchName: string) {
  let users: any[] = [];
  const queryBuild = await query(collection(db, 'users'), where('username', '>=', searchName));
  const querySnapshot = await getDocs(queryBuild);
  querySnapshot.forEach((doc) => {
    if (doc.data()) {
      users.push(doc.data());
    }
  });
  return users;
}

And this is the component:

export function Search({ navigation }: any) {
  // Redux
  const dispatch: any = useDispatch();
  const stock = useSelector((state: RootState) => state.stock);

  // Search
  const [search, setSearch] = useState<any>([]);

  async function fetchUsersProfile(username: string) {
    console.log('se', username);
    if (username.length > 0) {
      const result = await searchUsers(username);
      setSearch(result);
    } else {
      console.log('here');
      setSearch([]);
    }
  }

  async function followCurrentUser(uid: string) {
    await followUser(uid);
    dispatch(fetchUserFollowing());
  }

  async function unfollowCurrentUser(uid: string) {
    await unfollowUser(uid);
    dispatch(fetchUserFollowing());
  }

  useEffect(() => {}, [stock.following]);

  return (
    <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
      <Container>
        <InputField
          icon="search"
          placeholder="Search"
          onChangeText={(text) => fetchUsersProfile(text)}
        />

        <FlatList
          style={{ flex: 1, width: '100%', height: '100%' }}
          numColumns={1}
          horizontal={false}
          data={search}
          renderItem={({ item }) =>
            item.uid === stock.currentUser.uid ? (
              <></>
            ) : (
              <ContainerProfile>
                <TouchableOpacity
                  onPress={() =>
                    navigation.navigate('FoundProfile', {
                      data: item,
                    })
                  }
                >
                  <UserSearchContainer
                    username={item.username}
                    profileImage="data:image/jpeg;b"
                  />
                </TouchableOpacity>

                {stock.following.includes(item.uid) ? (
                  <ChipSmallButtonSecondary
                    text="Following"
                    onPress={() => unfollowCurrentUser(item.uid)}
                  />
                ) : (
                  <ChipSmallButtonPrimary
                    text="Follow"
                    onPress={() => followCurrentUser(item.uid)}
                  />
                )}
              </ContainerProfile>
            )
          }
        />
      </Container>
    </TouchableWithoutFeedback>
  );
}
1

There are 1 best solutions below

0
Frank van Puffelen On

To find values that start with a certain substring, you need both a start and an end condition. So add an extra where clause to your query:

query(
  collection(db, 'users'), 
  where('username', '>=', searchName), 
  where('username', '<=', searchName+"\uf7ff")
)

The "\uf7ff" here is the last known Unicode character, so that the query stops returning results once it encounters a username that doesn't start with searchName anymore.