In Firestore, how can you do a compound query involving a key in a map without creating an index for every key?

前端 未结 4 1905
旧时难觅i
旧时难觅i 2021-02-01 16:26

In Firestore, how can you do a compound query involving a key in a map without creating an index for every key?

For example, consider a collection which holds blog posts

相关标签:
4条回答
  • 2021-02-01 16:50

    Try restructuring your data store. Firebase documentation is very helpful here.

    Query limitations

    Cloud Firestore does not support the following types of queries:

    • Queries with range filters on different fields, as described in the previous section.
    • Single queries across multiple collections or subcollections. Each query runs against a single collection of documents. For more information about how your data structure affects your queries, see Choose a Data Structure.
    • Queries of individual array members. You can, however, model and query array-like data using the techniques in Working with Arrays, Lists, and Sets.
    • Logical OR queries. In this case, you should create a separate query for each OR condition and merge the query results in your app.
    • Queries with a != clause. In this case, you should split the query into a greater-than query and a less-than query. For example, although the query clause where("age", "!=", "30") is not supported, you can get the same result set by combining two queries, one with the clause where("age", "<", "30") and one with the clause where("age", ">", 30).
    0 讨论(0)
  • 2021-02-01 16:51

    This is doable by setting the value of each category to what you want to sort on. Firestore has a guide that covers this.

    Post {
        title: ..
        ...
        categories: {
            cats: createdAt
            puppies: createdAt
        }   
    }
    
    let query = db.collection(`/posts`)
        .where(`categories.${categoryId}`, '>', 0)
        .orderBy(`categories.${categoryId}`)
        .startAfter(lastDate)
        .limit(5);
    
    0 讨论(0)
  • 2021-02-01 17:09

    Now Firestore allows the array-contains operator.
    If you want to filter documents which contain specific value, try this.

    First, change Map field to Array field.

    Post {
        title: ..
        ...
        categories: [
            cats,
            puppies
        ]
    }
    

    Second, use array-contains and orderBy for each different fields.

    let query = db.collection(`/posts`)
        .where('categories', 'array-contains', 'cats')
        .orderBy('createdAt')
        .startAfter(lastDate)
        .limit(5);
    

    You can check the official document about array-contains operator from here.

    0 讨论(0)
  • 2021-02-01 17:11

    As far as I know Firestore should auto-generate those indexes. From the documentation page on arrays, lists, and sets:

    Consider this alternative data structure, where each category is the key in a map and all values are true:

    // Sample document in the 'posts' collection
    {
        title: "My great post",
        categories: {
            "technology": true,
            "opinion": true,
            "cats": true
        }
    }
    

    Now it's easy to query for all blog posts within a single category:

    // Find all documents in the 'posts' collection that are
    // in the 'cats' category.
    db.collection('posts')
        .where('categories.cats', '==', true)
        .get()
        .then(() => {
            // ...
        });
    )
    

    This technique relies on the fact that Cloud Firestore creates built-in indexes for all document fields, even fields in a nested map.

    While the lefthand-side of your where condition may be variable, that doesn't change the fact that these indexes should auto-generated (as far as I can see).

    0 讨论(0)
提交回复
热议问题