$elemMatch support (or alternative) - casl

I need to do an find operation on an array of objects in order to determine the permission, basically define a permission based on on whether an object exist in an array of objects defined as an attribute on the subject.
In MongoDB I would have used $elemMatch, is it supported? or do you recommend an alternative?
Example:
department = {
name: "name",
employees : [
{
Name: "John Doe",
title: "assistant"
},
{
Name: "Jane Doe",
title: "Manager"
}
]
};
I need to define an ability to only allow someone with the name "Jane Doe" and title "Manager" to update the name of the department.
Please do not focus on the very awful data model here, its just an example of what I am trying to achieve. The main focus is basing an ability on the existing of an object within a field that is an array of objects.
Fantastic library btw!

$elemMatch is supported. You can use it.

Related

Storing Partition Keys on CosmosDB

The concept is very straight away. Not difficulty to understand. But I can't find some practical examples... I've this json...
{
"agendaId": "688c99bc-c756-4b8f-9c39-60246c0ea66e",
"postId": "f07f16e5-e7d6-441e-bc1d-82ac671e0f63",
"name": "john doe"
}
And I defined this partition: /agendaId/postId
And then I inserted the item.
But I can't see any data on my CosmosDB Container Browser on the column of the partition key - I just can see the autogenerated Id...is this expected ?
/agendaId/postId means that the value is nested. The JSON to match that definition should be:
{
"agendaId": {
"postId": "f07f16e5-e7d6-441e-bc1d-82ac671e0f63",
},
"name": "john doe"
}
The / on the definition defines the level of nesting, so /attr1/attr2/attr3 would mean that the value is in attr3 that exists in attr2 which exists in attr1:
{
"attr1": {
"attr2": {
"attr3": "the value"
}
}
}
In your case, if you used, for example /agendaId is just the first level of attributes, or /postId. Both would pick up the value of the attributes in your document.
Reference: https://learn.microsoft.com/azure/cosmos-db/partitioning-overview#choose-partitionkey

Binding values to multiple labels in a List Widget; Using Dynamic Page Properties

Background:
I have a JSON object and I would like to bind it's values to a List Widget using a Dynamic Page Property. I am trying to set a dynamic page properties "value" to be a JSON Object, however I am not sure how to access that JSON's Approver's Elements.
Setting the Page Property "Value"
As I understand the dynamic page property should be able to accept a JSON object. In the below sample I do just that.
var jsonObject = {
"Approvers": [{
"Approver_Name": "John Doe",
"Approver_Email": "jdoe#email.com,",
"Approver_Status": "Pending"
}, {
"Approver_Name": "Jane Doe",
"Approver_Email": "jdoe2#email.com,",
"Approver_Status": "Pending"
}]
}
app.pages.editSubmission.properties.Approver_Details = jsonObject;
Accessing values in Page Property
I have read the documentation regarding properties and bindings. https://developers.google.com/appmaker/properties. I have tried the standard method of binding the List Widget's datasource to be Dynamic Page Property. (I am still not sure how access the elements of Approvers.)
Unfortunately the documentation doesn't cover dynamic properties. (Or I missed it.) If anyone can point me to some documentation or another stack overflow post covering this topic it would be greatly appropriated.
A List Widget expects its datasource to be an array of items, but you are providing a json object; hence it's not working. Instead of using a dynamic property use a <List>String property. That way you can do something like this:
var jsonObject = {
"Approvers": [{
"Approver_Name": "John Doe",
"Approver_Email": "jdoe#email.com",
"Approver_Status": "Pending"
}, {
"Approver_Name": "Jane Doe",
"Approver_Email": "jdoe2#email.com",
"Approver_Status": "Pending"
}]
}
app.pages.editSubmission.properties.Approver_Details = jsonObject.Approvers;
Then, when binding the values to your list, you can use three different labels inside the list row and each label has to be binded to the corresponding value:
#datasource.item["Approver_Name"]
#datasource.item["Approver_Email"]
#datasource.item["Approver_Status"]

How to query nested objects in firestore [duplicate]

This question already has answers here:
Firestore - Nested query
(2 answers)
Closed 2 years ago.
I want to store data in following format:
{
"chatName": "Football",
"chatMembers":
[
{
"userId": "nSWnbKwL6GW9fqIQKREZENTdVyq2",
"name": "Niklas"
},
{
"userId": "V3QONGrVegQBnnINYHzXtnG1kXu1",
"name": "Timo"
},
]
}
My goal is to get all chats, where the signed in user with a userId is in the chatMembers list. If the userId of the signed in user is not in the chatMembers property, then that chat should be ignored. Is this possible?
If this is not possible, how can i achive this with subcollections?
My development language is dart, but you can also post solutions in other languages.
My current attempt is this, but this is not working:
_firestore.collection(collectionName).where("chatMembers.userId", isEqualTo: userId).snapshots()
Since August 2018 there is the new array_contains operator which allows filtering based on array values. The doc is here: https://firebase.google.com/docs/firestore/query-data/queries#array_membership
It works very well with arrays of string. However, I think it is not possible to query for a specific property of an object stored in the array. One workaround is to query for the entire object, as follows (in Javascript). Of course this may not be feasible in every situation....
var db = firebase.firestore();
var query = db.collection('chatDocs').where("chatMembers", "array-contains", { userId: "xyz", userName: "abc" });
Renaud Tarnec's, which complete, doesn't work in every case. Situations where only one or not all of the fields are known won't return the expected documents. However, by restructuring the data in the document, a query can be made to work where only one field is known, like a user identifier (uid).
Here's the data structure inside one of the document:
{
"members": {
"user4": {
"active": true,
"userName": "King Edward III",
"avatar": "www.photos.gov/animeGirl5.png"
},
"user7": {
"active": true,
"userName": "Dave K.",
"avatar": "www.photos.gov/gunsAmericanFlag.png"
}
}
Here's the query:
uid = 'user4';
collectionQuery = collectionReference.where(`members.${uid}.active`,"==", true);
In this example, "user4" represents a user who may or may not be in a group. This will return all documents in the collection where the uid "user4" is an active member. This works by only needing to know the UID of the member and works without needing to know their name or avatar uri ahead of time.

How to create GTM data layer variable with complex array

In Google Tag Manager a pre-defined variable type of "Data Layer Variable" exists with an input for the variable name. In a standard single level of key/value pairs this is easy.
var dataLayer = [{"mykey":"myvalue"}];
Given that data layer you'd just use mykey as your variable to input into GTM. However, if you use the CEDDL spec (http://www.w3.org/2013/12/ceddl-201312.pdf) structure you end up with a deeply nested array:
dataLayer = [
{
"product": [
{
"category": {
"primaryCategory": "Auto Loans"
},
"productInfo": {
"productID": "1",
"productName": "PurchaseLoan",
"description": "Auto finance loan"
},
"security": [
"Analytics",
"Personalization",
"Recommendations"
]
}
]
}
]
So the real question is: how do I access the value of "productName" in the above example?
In standard Javascript you might access it like so:
dataLayer[1].product[0].productInfo.productName
or
dataLayer.1.product.1.productInfo.productName
... but neither of these options work (with or without dataLayer.1 as the first node).
This is the UI to enter the variable name:
When you define your DataLayer variable in GTM, you don't need to specify "dataLayer" in the variable name, ie. it should just be:
product.0.productInfo.productName

Mongo's elemMatch with meteor publish composite

I have a Mongo collection that looks similar to the below example, I am using meteor-publish-composite, https://atmospherejs.com/reywood/publish-composite to publish documents to the client. I know with Mongo I can do the following to return specific items within the authors array.
db.books.find({"authors.authorSlug": "author-1}, {authors: {$elemMatch: { authorSlug: "author-1"}});
When I try to achieve the same thing using meteor-publish-composite, this does not seem to work as it returns the entire the authors' array, my code is as below.
Books.find({"authors.authorSlug": slug}, {authors: {$elemMatch:{authorSlug: slug}}});
Is this even possible to achieve with publish-composite?
{
"title" : "Book1",
"authors" : [
{
"name" : "Author 1",
"authorSlug": "author-1"
},
{
"name" : "Author 2",
"slug" : "author-2"
},
],
"slug" : "book1"
}
You only use publish-composite when you are trying to join 2 or more related collections into a single reactive subscription. You simply need a standard publish/subscribe for your collection - and you say you have working code so I don't see what your problem is! Or are you trying to get at your books data in addition to other data around it?

Resources