How to query a firestore array with multiple key value pairs in Swift - swift

One of my collections in Cloud Firestore has an where each item in the array contains three separate values (see the groupMembership field:
I know I can't write a query to find documents that match one of the array values. Is there a way to write a query to find documents that match a specific value for all three items?
For instance, I want to find all users where the groupMembership array contains one object that is equal to groupId: X, groupName: Y, membershipStatus: active

You can pass the entire object in an array-contains clause.
So something like:
usersRef
.whereField("groupMembership", arrayContains: [
"groupId": "kmDT8OUOTCxSMIBf9yZC",
"groupName": "Jon and Charles Group",
"membershipStatus": "pending",
])
The array item must completely and exactly match the dictionary you pass in. If you want to filter only on some of the properties in each array element, you will have to create additional fields with just those properties. For example, it is quite common to have say a field groupIds with just the (unique) group Ids, so that you can also filter on those (of course within the limits of Firestore's queries).

Related

I need to get a specific document, where a document contains exactly two specific values

.collection('chats')
.where('members',
arrayContains: List.of([user1,user2]))
.snapshots();
I need to get a specific document, where 'members' contains exactly 'user1' and 'user2' only, and not just one of the values.
Also very important that the order of the values inside the 'members' array/list should be irrelevant..
Because this method using arrayContains is giving me any document that contains either one of these users.
What you're trying to do isn't possible exactly as you've specified. But you can do this if you assume the order of the elements in the array. For that, use a normal isEqualTo filter, providing the exact contents of the array to match. I don't write dart, but it should go something like this:
.where('members', isEqualTo: List.of([user1,user2]))
You can make sure the array always has a consistent order by sorting the items in the array before writing the field, and sorting the array you use in the query.
If the original order of the array is important, then maintain a duplicate field with the same array elements that are always sorted, and query that field instead of the original field.
See also:
FireStore query how to query arrays from the database

How to use dot notation in Cloud Firestore to query nested properties in a list of maps

So I have a collection of documents in cloud firestore where each document has this structure:
{
key1: value1
key2: value2
access: [{key: {key: value, key: value}, users: [...keys]},]
}
From a widget I want to get the documents where the id that I have exists in the users array. My query is this: labs.where('access.users', arrayContains: user.id).get()
I have read that in order to query nested elements you need dot notation. My problem is that it results in an error -> Bad state: No element. Which I assume is, because firestore doesn't know which access.users to query on since it is a list, but on the other hand I imagine that it should take each map one by one.
Maybe I'm missing something in my logic. Help is appreciated.
As Dharmaraj commented, the arrayContains operator checks whether the array contains an item that is exactly the same as you pass to it. There is no way to pass a partial object to arrayContains and check for the presence of just that part.
The common workaround is to create an additional array field that just contains the values you also want to query on. So in your case that'd be an array of the UIDs that have access:
access_users: ["uid1", "uid2", "uid3"]
And then your query would become:
labs.where('access_users', arrayContains: user.id).get()

How can you create a Firestore compound query that returns all documents in an array of mapped objects?

I want to avoid returning documents from Firestore that I do not need. I have a collection of documents with the following properties:
membership {array}
0 {map}
contactGroupId: "1da9a73f89f8ca4c"
contactGroupResourceName: "contactGroup/1da9a73f89f8ca4c"
1 {map}
contactGroupId: "1da9a73f89f8ca4c"
contactGroupResourceName: "contactGroup/1da9a73f89f8ca4c"
I want to create a compound query that only returns documents if the contactGroupId is equal to 1da9a73f89f8ca4c. Something like ref.where(membership.{key}.contactGroupId, "==", "1da9a73f89f8ca4c"). Is this possible?
It's not possible to filter documents using the contents of a map field inside an array. You will need to restructure your data if you want to perform this query. You have two options.
Put all of the contactGroupId values into their own array field, and use an array-contains query to find them.
Instead of using an array, use the contactGroupId value as the name of a map key that you can use in a query, like where(membership.1da9a73f89f8ca4c.present, '==', true). Your membership field would be structure like this:
membership (map)
- 1da9a73f89f8ca4c
- present (boolean)
- contactGroupResourceName = "contactGroup/1da9a73f89f8ca4c"

Check which elements of an array belong to a collection without using loop?

I have a collection of 10000 items in MongoDB. The front end user submits an array of 100 items, and wants to know which of the 100 items belong to my collection.
Can I query it without using a loop?
Thanks!
----update: "more details" requested by comment:----
Sure, let's suppose my collection is about books (_id, book title, author name). Front end user submits an array of book titles. I need to answer which of the titles can be found in the db.
Also, suppose the book titles are always unique on both ends.
you can just use the $in operator which expects an array with titles of books and it should return the objects which contain the same.
db.getCollection('book').find({ title: { $in: ["string1", "string2"] }})

ODM Query Builder: Is there an "inverse in" operator, or equivalent operation?

In my synfony 2 project, I'm filtering search results using a query builder. In my MongoDB i have some values in an array.
Query Bulider has the "in" operator that allows to query for values that equal one of many in an array. I wanted to perform the opposite operation, i.e. given a single value, query for entries in the data base that contain an array, that contains my value.
For instance, say I have this entry in my MongoDB:
{
"_id": 123,
"name": "John",
"countries_visited":
[
"Australia"
"Bulgaria",
"Canada"
]
}
And I want to query my database for persons who have visited "Canada". Right now, I'm using the where attribute as follows, but I'm looking for a better way to do this.
$qb->field('countries_visited')->where("function(){
return this.indexOf(".$countryName.") > -1
}");
edit:
The in and notIn operator receives an array as parameter and compares it against a single value in MongoDB. I need to provide a single parameter and apply it to an array field in MongoDB, hence "inverse in". I guess I need a contains operator if there's such a thing.
Interesting, MongoDB takes care of this automatically. If querying for a single value against an array field, Mongo will assume you want the check the array if it contains the value.
Taken from the docs:
Match an Array Element
Equality matches can specify a single element in the array to match. These specifications match if the array contains at least one element with the specified value.
So you should be able to do
$users = $dm->getRepository('User')->findOneBy([
'countries_visited' => 'Canada'
]);
or
$qb->field('countries_visited')->equals('Canada');