Executing `Collection.firstWhere().exists()` should return `true` or `false`

Expected

Executing Collection.firstWhere().exists() should return true or false.

Problem

But Collection.firstWhere() can return null, leading to the fact, that .exists() is throwing an invalid_null_access error because fauna is not auto resolving null to false.

exists() does return true or false.

But the return type of first() and firstWhere is a YourDocumentType | Null

image

The exists method only exists on Documents and “NullDocs”. exists() is used to check if a reference is in the database. A NullDoc are like a a pointer we know points at nothing because either it doesn’t exist or you don’t have permission to it. When you use .byId that method either returns a document or NullDoc,

image

A NullDoc is like a bad reference, but it has information about what it is at least trying to look up. The reason we have NullDoc is because this reference may actually point to something in the future, so it is good to keep the Collection and ID info around. You may also want to know that reason (does not exist or no permissions).

When you use first and firstWhere you are requesting a document. It makes sense that if one exists you get it. But what should we do if one does not exist? There is literally nothing to return, not even some reference for you to check if it exists, so we return null.

The type of first and firstWhere is YourDocumentType | Null so you can assume that if it’s not null it’s a document. Don’t use exists() but compare against null.

Question.all().firstWhere(.title.startsWith("old")) != null
1 Like

I understand the argument. My point of view is more about intuitivity, consistency and learning curve.
I understand that a statement like null.exists() is not ideal. But rather than having two different patterns like != null and .exists(), I would prefer if there is one streamlined experience.

Can you share what you need in the greater context? Does your logic truly depend only on checking if a Set has at least one document in it, or do you end up using that document if it does exist?

I ask because maybe the problem is a lack of .exists() on the Set type. For example in v4, you can do Exists(Documents(Collection("MyCollection")) which returns false if there are zero documents in the Collection. The equivalent in v10 would be something like MyCollection.all().exists(), but that isn’t allowed. From this perspective, doing MyCollection.all().first() != null is the correct workaround.

That said, if your real example needs to use the first document if it exists, then it may read better to use an intermediate variable. In that case, first() or firstWhere methods are the way to go, and the existing types and methods are appropriate for the task.

let maybeDoc = Question.all().firstWhere(.title.startsWith("old"))

if (maybeDoc != null) {
  // do something with the doc
} else {
  // handle null case
}

My use case is checking if the document exists and then using it.

Maybe then the way to go is with maybeDoc != null because, based on your explanations, it seems to me that it covers everything as .exists() but also covers the empty/null case.(Except chaining)
Is that true?

Because then, eventually, .exists() could be deprecated in favor of simplicity.

My apologies @Mike, Sets alread have an isEmpty method. Which I think solves your original request.

MyCollection.where(.title.startsWith("Name")).isEmpty()