50

Let's say I have a data model with some optional properties. This could be for example a user object with a "firstname", a "lastname" and an optional "website" property.

In Cloud Firestore only user documents with a known website would have the "website" property set, for all other user documents this property would not exist.

My questions is now, how to query for all user documents without a "website" property?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
The Lone Coder
  • 3,062
  • 4
  • 20
  • 35

1 Answers1

47

Documents can contain properties with a null value data type (see data types documentation). This will then allow you to construct a query to limit results where the website property is null.

This is not quite the same as a missing property, but if you use custom objects to write data to Firestore, empty properties will automatically be saved as null rather than not at all. You can also manually/programmatically write a null value to the database.

In Android, I tested this using the following:

FirebaseFirestore.getInstance().collection("test").whereEqualTo("website", null).get();

Where my database structure looked like:

example firestore structure

This returned only the document inuwlZOvZNTHuBakS6GV, because document 9Hf7uwORiiToOKz6zcsX contains a string value in the website property.

I believe you usually develop in Swift, where unfortunately custom objects aren't supported, but you can use NSNull() to write a null value to Firestore. For example (I'm not proficient in Swift, so feel free to correct any issues):

// Writing data
let docData: [String: Any] = [
    "firstname": "Example",
    "lastname": "User",
    "website": NSNull()
]
db.collection("data").document("one").setData(docData) { err in
    if let err = err {
        print("Error writing document: \(err)")
    } else {
        print("Document successfully written!")
    }
}

// Querying for null values
let query = db.collection("test").whereField("website", isEqualTo: NSNull())

The documentation doesn't mention a method to query for values that don't exist, so this seems like the next best approach. If anyone can improve or suggest alternatives, please do.

Grimthorr
  • 6,856
  • 5
  • 41
  • 53
  • 2
    After contemplating this a bit, it probably needs to be this way for indexing to work. If a property is not set at all, it is probably not indexed and therefore cannot be queried. Setting the property to null will add the document to the respective index for the property. One comment to your code: I will try it later myself but in theory your example should also work using the Swift "nil" instead of NSNull(). Thanks again. – The Lone Coder Oct 19 '17 at 08:02
  • Is it possible to build the same query which selects only the documents based on fileds which are NOT equal to null? For example, select only the documents which contain non-null value for the 'website' field? Firestore doesn't offer the `isNotEqual` operator, so does that mean that we have to fetch all documents, and manually perform the filtering? – ElectroBuddha Mar 04 '18 at 11:19
  • 2
    Update: found the solution for checking for non-null values [here](https://stackoverflow.com/a/48481812/4218640). – ElectroBuddha Mar 04 '18 at 11:34
  • Instead of `NSNull()` you can use a bit longer but swiftier `Optional.none as Any` – ramzesenok Jul 17 '22 at 21:12