Firestore query documents startsWith a string

You can but it's tricky. You need to search for documents greater than or equal to the string you want and less than a successor key.

For example, to find documents containing a field 'foo' staring with 'bar' you would query:

db.collection(c)
    .where('foo', '>=', 'bar')
    .where('foo', '<', 'bas');

This is actually a technique we use in the client implementation for scanning collections of documents matching a path. Our successor key computation is called by a scanner which is looking for all keys starting with the current user id.


same as answered by Gil Gilbert. Just an enhancement and some sample code. use String.fromCharCode and String.charCodeAt

var strSearch = "start with text here";
var strlength = strSearch.length;
var strFrontCode = strSearch.slice(0, strlength-1);
var strEndCode = strSearch.slice(strlength-1, strSearch.length);

var startcode = strSearch;
var endcode= strFrontCode + String.fromCharCode(strEndCode.charCodeAt(0) + 1);

then filter code like below.

db.collection(c)
.where('foo', '>=', startcode)
.where('foo', '<', endcode);

Works on any Language and any Unicode.

Warning: all search criteria in firestore is CASE SENSITIVE.


Extending the previous answers with a shorter version:

  const text = 'start with text here';
  const end = text.replace(/.$/, c => String.fromCharCode(c.charCodeAt(0) + 1));

  query
    .where('stringField', '>=', text)
    .where('stringField', '<', end);

IRL example

async function search(startsWith = '') {
  let query = firestore.collection(COLLECTION.CLIENTS);

  if (startsWith) {
      const end = startsWith.replace(
        /.$/, c => String.fromCharCode(c.charCodeAt(0) + 1),
      );

      query = query
        .where('firstName', '>=', startsWith)
        .where('firstName', '<', end);
  }

  const result = await query
    .orderBy('firstName')
    .get();

  return result;
}

If you got here looking for a Dart/Flutter version

Credit to the java answer by Kyo

final strFrontCode = term.substring(0, term.length - 1);
final strEndCode = term.characters.last;
final limit =
  strFrontCode + String.fromCharCode(strEndCode.codeUnitAt(0) + 1);

final snap = await FirebaseFirestore.instance
  .collection('someCollection')
  .where('someField', isGreaterThanOrEqualTo: term)
  .where('someField', isLessThan: limit)
  .get();

The above are correct! Just wanted to give an updated answer!

var end = s[s.length-1]
val newEnding = ++end

var newString = s
newString.dropLast(1)
newString += newEnding

query
  .whereGreaterThanOrEqualTo(key, s)
  .whereLessThan(key, newString)
  .get()