Google Firestore: Query on substring of a property value (text search)

前端 未结 16 1330
抹茶落季
抹茶落季 2020-11-22 12:08

I am looking to add a simple search field, would like to use something like

collectionRef.where(\'name\', \'contains\', \'searchTerm\')

I tried

16条回答
  •  隐瞒了意图╮
    2020-11-22 12:47

    As of today, there are basically 3 different workarounds, which were suggested by the experts, as answers to the question.

    I have tried them all. I thought it might be useful to document my experience with each one of them.

    Method-A: Using: (dbField ">=" searchString) & (dbField "<=" searchString + "\uf8ff")

    Suggested by @Kuba & @Ankit Prajapati

    .where("dbField1", ">=", searchString)
    .where("dbField1", "<=", searchString + "\uf8ff");
    

    A.1 Firestore queries can only perform range filters (>, <, >=, <=) on a single field. Queries with range filters on multiple fields are not supported. By using this method, you can't have a range operator in any other field on the db, e.g. a date field.

    A.2. This method does NOT work for searching in multiple fields at the same time. For example, you can't check if a search string is in any of the fileds (name, notes & address).

    Method-B: Using a MAP of search strings with "true" for each entry in the map, & using the "==" operator in the queries

    Suggested by @Gil Gilbert

    document1 = {
      'searchKeywordsMap': {
        'Jam': true,
        'Butter': true,
        'Muhamed': true,
        'Green District': true,
        'Muhamed, Green District': true,
      }
    }
    
    .where(`searchKeywordsMap.${searchString}`, "==", true);
    

    B.1 Obviously, this method requires extra processing every time data is saved to the db, and more importantly, requires extra space to store the map of search strings.

    B.2 If a Firestore query has a single condition like the one above, no index needs to be created beforehand. This solution would work just fine in this case.

    B.3 However, if the query has another condition, e.g. (status === "active",) it seems that an index is required for each "search string" the user enters. In other words, if a user searches for "Jam" and another user searches for "Butter", an index should be created beforehand for the string "Jam", and another one for "Butter", etc. Unless you can predict all possible users' search strings, this does NOT work - in case of the query has other conditions!

    .where(searchKeywordsMap["Jam"], "==", true); // requires an index on searchKeywordsMap["Jam"]
    .where("status", "==", "active");
    
    

    **Method-C: Using an ARRAY of search strings, & the "array-contains" operator

    Suggested by @Albert Renshaw & demonstrated by @Nick Carducci

    document1 = {
      'searchKeywordsArray': [
        'Jam',
        'Butter',
        'Muhamed',
        'Green District',
        'Muhamed, Green District',
      ]
    }
    
    .where("searchKeywordsArray", "array-contains", searchString); 
    

    C.1 Similar to Method-B, this method requires extra processing every time data is saved to the db, and more importantly, requires extra space to store the array of search strings.

    C.2 Firestore queries can include at most one "array-contains" or "array-contains-any" clause in a compound query.

    General Limitations:

    1. None of these solutions seem to support searching for partial strings. For example, if a db field contains "1 Peter St, Green District", you can't search for the string "strict."
    2. It is almost impossible to cover all possible combinations of expected search strings. For example, if a db field contains "1 Mohamed St, Green District", you may NOT be able to search for the string "Green Mohamed", which is a string having the words in a different order than the order used in the db field.

    There is no one solution that fits all. Each workaround has its limitations. I hope the information above can help you during the selection process between these workarounds.

    For a list of Firestore query conditions, please check out the documentation https://firebase.google.com/docs/firestore/query-data/queries.

    I have not tried https://fireblog.io/blog/post/firestore-full-text-search, which is suggested by @Jonathan.

提交回复
热议问题