简体   繁体   中英

Firebase Firestore - OR query alternative

In this question Firebase Firestore - OR query they said there is no OR query. This means I can't easily query for items that have an ID that is in an array I got earlier.

// What I want
documentRef
    .whereField("itemId", isEqualTo: "id1")
    .orWhereField("itemId", isEqualTo: "id3")

// or
documentRef
    .whereField("itemId", in: idArray)

Since this doesn't work, what option is better to query my data?


  1. Get all the data and check locally

I could get all my records and just check the IDs on the device but the problem is that it can be up to 1000 records and the user might only need three of them.


  1. Do separate queries for all items

I could just do a query whereField("itemId", isEqualTo: "id") for each item that the user needs. This would be good if the user only needs a few of the items but it is possible the user needs all the items and this solution would become a lot slower than the first one. (unless you could batch reads)


  1. Move data

I think I could move the purchased data to the Item collection: Items/itemid/PurchasedBy/uid but I want to retrieve the Item that a user has bought and I don't know how to query an Item by a field inside a nested collection. I also don't know if this would be the correct place for the data.


My Data:

Users/uid/PurchasedItems/itemid

    payedInMoney: "$0.00"
    payedInCoins: "100"
    itemId: "itemid"
    timeStamp: timestamp

Items/itemid

    itemId: "itemid"
    // Other item info

Edit:

I made the first option because that is how I did it on RTDB but even with persistence on and using addSnapshotListener Firestore doesn't even come close to the speed of the RTDB implementation. I clocked the times and it looks like Firestore is at least 4x as slow as RTDB (both with persistence enabled).

// iPad 5 (2017) - iOS 11
RTDB:  50-100ms
FST:  350-450ms

// iPad Air (2014) - iOS 10
RTDB: 100-150ms
FST:  700-850ms

// iPad Mini (2012) - iOS 9
RTDB: 150-200ms
FST:  2900-3200ms

Edit 2:

Decided to stick with RTDB until persistence on Firestore really works.

Edit 3:

The accepted answer fixes the problem in this question and even though it doesn't fix all mine, it might help someone else.

After tests using only one query with Firestore the result still takes longer to come through than doing the nested query in RTDB so I will stick with my decision for now.

This seems like a good case for duplicating some of the item data. I assume that some item properties like "name" are immutable and can therefore be stored in the PurchasedItems subcollection without worrying about future updates.

So if you add some of the data to PurchasedItems :

Users/uid/PurchasedItems/itemid

    // Existing 
    payedInMoney: "$0.00"
    payedInCoins: "100"
    itemId: "itemid"
    timeStamp: timestamp

    // Add these
    name: "Item Name"
    url: "http://foo.bar/123"

Then you will have enough information to display the list of a user's purchased items in a single query without needing to also look up each item by ID.

You could combine the Observables using rxjs;

orQuery(){

    const $one = this.afs.collection("items", ref => ref.where("itemId","==","1")).valueChanges();
    const $two = this.afs.collection("items", ref => ref.where("itemId","==","3")).valueChanges();

    return combineLatest($one,$two).pipe(
        map(([one, two]) => [...one, ...two])
    )
}

getOr(){
    this.orQuery().subscribe(data => console.log(data))
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM