Firestore query with where(in:) and where(isEqual:) - ios

Is the following composite where(in:) and where(isEqualTo:) query possible in Firebase Firestore?
(Swift)
let taskDocIds = ["0ArJnMgTfDkvolUcZR8E", "0cdcZsfaEJQpsiByJIgH"]
return db.collection("tasks")
.whereField("status", isEqualTo: "approved")
.whereField(Firebase.FieldPath.documentID(), in: taskDocIds)
.limit(to: 100)
.getDocuments(as: TaskModel.self)
My security rules enforce that only tasks with status as approved may be read. However the the query above results in an error (see below) when the status of any of the tasks whose id is in the taskDocIds array has a status other than approved.
Error: Domain=FIRFirestoreErrorDomain Code=7 "Missing or insufficient permissions."
If the query is possible, does a composite index need to be created? And if so, how does one go about configuring that manually (using Firebase Console) for a FieldPath document id?

Permission errors can never be resolved by adding an index.
The problem is that the rule doesn't know if your entire set of taskDocIds would be allowed without checking them all individually. Firebase security rules are not filters, so, when performing a query, the rule will not read and check each document individually and give you only the ones that match. Without assurance that every document that could match the query absolutely does match the query, it simply fails the entire rule.
Your alternative is to simply getDocument() each one individually. With individual document gets, the rule will check the individual fields of the document.

Related

How to fix 'sqlite3' and other errors in CallKit Directory extension?

The idea of the app is to add around 50.000 contacts to the CallKit Directory, but when I try to add them with context.addIdentificationEntry(withNextSequentialPhoneNumber: contact.number, label: contact.contactLabel) in the beginRequest(with context: CXCallDirectoryExtensionContext) method i often either get a com.apple.CallKit.error.calldirectorymanager error 2 or some strange sqlite3 error:
sqlite3_step for query 'INSERT INTO PhoneNumberIdentificationEntry
(extension_id, phone_number_id, label_id) VALUES (?, (SELECT id
FROM PhoneNumber WHERE (number = ?)), (SELECT id FROM Label WHERE
(localized_label = ?))),
…
(SELECT id FROM Label WHERE (localized_label = ?)))' returned 19
(2067) errorMessage 'UNIQUE constraint failed:
PhoneNumberIdentificationEntry.extension_id,
PhoneNumberIdentificationEntry.phone_number_id,
PhoneNumberIdentificationEntry.label_id'
Generally I fetch the contacts from a server and try to keep them in sync - therefore, I save them locally with Realm. Has anyone ideas how to handle such errors?
Since I could not find much solutions to CallKit Directory errors, I tried to fix the errors by myself. It took me some time and to save some time for other developers I try to sum up all errors I got during the implementation of the CallKit Directory Extension with a suggested solution for each of them - I cannot guarantee that these solutions work for 100% but maybe they still can help!
sqlite3_step error: I often got the error when I tried to sync the contacts again, therefore I guess, that the error is some kind of duplicate error. Since it is possible that a contact has two numbers, I used the same name for both entries which basically worked, but I think there is still some kind of identification problem in the background if you use the exact same name for the label. Therefore, I added the index of each contact at the end of the label to keep them unique and now the error does not appear again anymore. (Even if all of your contacts have only one number keep in mind, that there are maybe some contacts with the same first and last name.)
com.apple.CallKit.error.calldirectorymanager error 2: This error appears often due to memory problems. Extension have much less memory available than the app itself (CallKit Directory Extension has for example only 12 MB available). To prevent this error I used a paging mechanism which always only loads a specific amount of contacts into the extension and then gets reloaded with the next page. If you use Realm there are additionally two aspects to consider: First, set the used object types in the Realm configuration Realm(configuration: Realm.Configuration(fileURL: realmFileURL, objectTypes: [ContactObject.self])) - this prevents Realm from calling objc_copyClassList() which needs a lot of memory. Second, if you filter the realm objects which a specific predicate try to avoid using any kind of references in the filter - for example, first, after adding the contact to the CallKit Directory, I passed the number of the contact to the filter of the realm objects to mark that contact as synced. But then I saw that the memory in the extension increased with each synced contact since there were probably some kind of references to the contact object. Then, I fetched the exact same page of contacts to mark them all as synced instead of fetching them one by one which allowed me to load much more contacts per page. Tip: If you want to use Breakpoints in the extension or want to debug the memory of the extension go in Xcode to Debug -> Attach to Process -> AppName Call Directory. Then you can select the call directory in the debug navigator and see the used amount of memory. (You can only attach to the extension process when it is currently used - just in case you can’t see it in the list)
com.apple.CallKit.error.calldirectorymanager error 3: The contact numbers are not ordered - order them before adding them to the directory.
com.apple.CallKit.error.calldirectorymanager error 4: Duplicated Entries - ensure to add a number only once.
Please do not hesitate to correct me if I am wrong with any of these suggestions or to add further tips and solutions - otherwise I am glad if I could help!
It seems like you're adding duplicate contacts. Just make sure the contacts you're adding are unique.

Retrieving More columns as Part of VSTS query

I'm trying to fetch details from VSTS using VSTS query API. So to get all Portfolio Epics I created a custom query and used its ID to get that in JSON format. the query looks like this
https://dev.azure.com/{organization}/{project}/{team}/_apis/wit/wiql/{id}?api-version=5.0-preview.2
But the issue is its not giving me many details about each of the work items in JSON. It only lists the ID and URL. Like this
WorkItems:[
{ID:234,URL:"workitemurl"},
{ID:235,URL:"workitemurl"},
{ID:236,URL:"workitemurl"},
...
]
So if I need more details about an item I need to execute those individual URl for each PE and thus I can get its details. instead of I am just checking is there is any way of getting an ID (keyedinID of each work item along with the ID and URL) like this. Please note KID is a field if we execute the URL separately. So to avoid that extra process, I would like to get that along with the WorkItems.
WorkItems:[
{ID:234,URL:"workitemurl",KID:002},
{ID:235,URL:"workitemurl",KID:023},
{ID:236,URL:"workitemurl",KID:033},
...
]
So how can we make this possible?
The Web UI uses a different API to get query results (/_api/_wit/_query), which allows query+data in a single pass. This is an old __v5 type call, which means it's considered internal.
The proper way to do this now is to first do the query as you're doing it right now and then call /_api/wit/workitems?ids=1,2,3,4 using the IDs from the references you got from the first call. That will also allow you to load the details dynamically and in small batches which will result in a more responsive UI.
See:
https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/work%20items/list?view=azure-devops-rest-4.1

Microsoft Graph HonorNonIndexedQueriesWarningMayFailRandomly Error when filtering SharePoint Online lists

I'm using ms-graph with SharePoint Online.
I've a simple list with a single title column and 3 items.
I use the following ms-graph call to filter items by title:
https://graph.microsoft.com/v1.0/sites/root:/lists/list-guid/items?expand=fields&filter=startswith(fields/Title,%27fig%27)
The result is an error message:
Field 'Title' cannot be referenced in filter or orderby as it is not indexed. Provide the 'Prefer: HonorNonIndexedQueriesWarningMayFailRandomly' header to allow this, but be warned that such queries may fail on large lists.
I know that this call was working before and also when I use SharePoint REST API then I can filter the list without any problems. I also tried different tenants.
Another fact is that the same call is working without the startswith filter.
Few days ago I had a different message for the same call.
"Field 'Title' cannot be referenced in filter or orderby as it is not indexed. Provide the 'allowthrottleablequeries' preference to allow this, but be warned that such queries may fail on large lists."
Regarding the following error:
Field 'Title' cannot be referenced in filter or orderby as it is not
indexed. Provide the 'Prefer:
HonorNonIndexedQueriesWarningMayFailRandomly' header to allow this,
but be warned that such queries may fail on large lists.
at least two options are available to surpass this error while filtering.
Option 1. Add an index to a SharePoint column
Once the index to a SharePoint column which participates in filtering is created, the error should no longer appear.
Option 2. Append header Prefer:HonorNonIndexedQueriesWarningMayFailRandomly
As the error message states append the specified header to request, for example in Graph Explorer:
Just checked the Graph API Explorer and found out that you can use allowthrottleablequeries rather than HonorNonIndexedQueriesWarningMayFailRandomly
Try to send your request with the following Request Header
Prefer: allowthrottleablequeries

Firebase check for existing email with relative/wildcard path

Im trying to check the emails of my users in my firebase database, if their email already exists. My json looks like that:
I dont know how to get the full path to email, because every User starts with the Unique Identifier and I dont have that information. Is it possible to use a wildcard /users/*/email or something like that?
this.afdb.database.ref('users/*/email').orderByChild('email').on('value', (snapshot)=>{
console.log(snapshot);
});
When a Firebase Database query runs against a location, it considers each child node under that location. And for each child node you can test the value of properties at a known path under that child.
There is no support for wildcards, nor does one seem needed for your case here:
this.afdb.database.ref('users').orderByChild('email').equalTo("pqoo#poam.com").on('value', (snapshot)=>{
snapshot.forEach((child) => {
console.log(child.val());
});
});
So the two changes are:
We query location users order by email and only return nodes with value pqoo#poam.com.
There will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result. So we use snapshot.forEach(...) to loop over the results.

Select fields on Microsoft Graph list of Messages

I'm using Microsoft Graph to get a list of messages for a user.
I'm using the following URL
https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages
One important thing that is returned by this is the meetingMessageType when the message revolves around a meeting request.
I would also like to get the uniqueBody of the message. However, that's not provided by default. One needs to specifically ask for that field. I can do that by adding ?$select=uniqueBody to the URL.
However, that now means that I need to add the rest of the fields I want to the $select query parameter. That's not a big deal until I run into meetingMessageType. Microsoft Graph returns:
Could not find a property named 'meetingMessageType' on type 'Microsoft.OutlookServices.Message'.
What can I do to ensure I get both uniqueBody and meetingMessageType?
Try this:
$select=uniqueBody, microsoft.graph.eventMessage/meetingMessageType
Yogesh's answer is close but will result in a Only one level select is supported error.
As long as you don't care about the value of meetingMessageType, you can use this select:
$select=microsoft.graph.eventMessage, uniqueBody
You'll note that the results no longer include meetingMessageType as a property. The list however is limited to only those messages that are eventMessage, effectively giving you a result set filtered to only show meeting requests.

Resources