samuelgozi/firebase-firestore-lite

How to query?

sdhull opened this issue · 4 comments

I guess I don't really understand how to use the API in this library for querying my data. I have a query set up like this:

      const apps = await collectionRef.get({
        where: [["myArray", "array-contains", myVal]],
        limit: 1,
      });

But I get back the response:

error: {code: 400,}
code: 400
message: "Invalid JSON payload received. Unknown name "where": Cannot bind query parameter. Field 'where' could not be found in request message.↵Invalid JSON payload received. Unknown name "limit": Cannot bind query parameter. Field 'limit' could not be found in request message."
status: "INVALID_ARGUMENT"

I'm sorry, Query is the only undocumented feature so far.
It's different from the official SDK, but it's more in line with the internal implementation of Firestore and therefore is a bit more powerful.

Here is the gist of it:
After creating a reference, call the query method of it with the necessary options.
The options are documented here:
https://github.com/samuelgozi/firebase-firestore-lite/wiki/Query-instance#queryoptions--object

If you are having trouble and want a working example, please let me know, I will happily do so.
And if you have any suggestions, please let me know.

BTW: Calling the get method with an object didn't work, get expect different kinds of options that most devs won't use, but in case you are curious, let me know and ill explain more.

Edit: Here is how to perform the query you tried to:

      const apps = await collectionRef.query({
        where: [["myArray", "contains", myVal]],
        limit: 1,
      });

Edit 2: Here are all the valid where operators. I noticed they weren't documented.

  • <: Less than.
  • <=: Less than or equal
  • >: Greater than
  • >=: Greater than or equal
  • ==: Equal
  • contains: Only for arrays. Checks if the array contains the value.
      const apps = await collectionRef.query({
        where: [["myArray", "contains", myVal]],
        limit: 1,
      });

This isn't quite right either. This simply instantiates a new Query, so it's not an async call. I think what it's supposed to be is this:

      const appsQuery = collectionRef.query({
        where: [["myArray", "contains", myVal]],
        limit: 1,
      });
      const apps = await appsQuery.run();

However this throws Query.js:302 Uncaught TypeError: Cannot read property 'fetch' of undefined and digging in, it's not too hard to see why. On this line you set options.from to a simple pojo with no db property. So calling this.options.from.db returns undefined every time.

You are right, again. To be honest, I'm writing the documentation for this(at this very moment) and I noticed that, along with some other issues. Expect a fix in the next minutes, along with better documentation.

And yes, I forgot to tell you to use the run() method to actually make the request(if you noticed, the run method doesn't really return the results either, there is a missing return, but it'll be fixed in the next push).

Update: It took more than just a few minutes, but I fixed it as well as some other issues.
There are some backward compatible syntactic changes that allow for cleaner code, for example, instead of writing an array for just one option in the where prop:

{
where: [["myArray", "contains", myVal]]
}

You can now just write it this way:

{
where: ["myArray", "contains", myVal]
}

In addition, there are better error messages that are more useful.
Hopefully this week I'll do a complete refactor to make the implementation faster, and also improve on some other areas.

Make sure to update to version 0.4.1 or above, and take a look at the docs for documentation(The API reference will be updated in the future).

If I forgot something, feel free to reopen the issue.