class Person{
#Persistent
private List tags = ArrayList()
}
I want to let the user query a person based on his/her tag, so I had my query filter like this:
tags.contains(tagValue1)
and if the user want to search for multiple tags, I would just add to the filter so if the user is searching for 3 tags, then the query would be
tags.contains(tagValue1) && tags.contains(tagValue2) && tags.contains(tagValue3)
I think this approach is wrong, because the datastore then needs to have an index that have the tags property three times... and if the user search for more than 3 tags at a time then it will be broken.
What's the proper way to do this? Do you guys have any suggestions?
Can't answer on the specifics of how GAE/J's plugin processes that but a marginally better query would be
tags.contains(theTag) && (theTag == tagValue1 || theTag == tagValue2 || theTag == tagValue3)
so "theTag" is a variable.
Related
This question already has answers here:
Firestore Security - allow only known fields
(3 answers)
Closed 3 years ago.
My user login system will automatically create a new document in the database collection when somebody signs up with a new phone number.
The creation and updating of user document is done through the client side JavaScript and I am using the firestore security rules for preventing a basic user from writing or modifying document properties like isActivated and isAdmin. It will work with below rule:
allow write: if request.response.data.isActive==null || request.response.data.isActive == response.data.isActive &&
request.response.data.isAdmin==null || request.response.data.isAdmin == response.data.isAdmin;
But still some hacker guys can easily modify the dbRef.add() function on the client side and add useless data like {age: "hacker won't tell ya", hackersName: "Naah!", foo: "bar", bar: "foo"} and so on.
I want the user document to hold only the properties name, phone_number, isActive, isAdmin, FCMtoken and nothing else. Did anybody else fall into the same trouble?
and any idea for accomplishing this?
To assert that a resource only has a certain list of keys, you can use rules.List#hasOnly() which will evaluate to false if a value appears that is not in the given list.
request.response.data.keys().hasOnly(['name', 'phone_number', 'isActive', 'isAdmin', 'FCMtoken'])
Combining this with your other (fixed) restrictions, gives:
allow write: if (request.response.data.isActive == null || request.response.data.isActive == response.data.isActive)
&& (request.response.data.isAdmin == null || request.response.data.isAdmin == response.data.isAdmin)
&& request.response.data.keys().hasOnly(['name', 'phone_number', 'isActive', 'isAdmin', 'FCMtoken']);
I'm currently working on my firestore rules and I need to validate the incoming data. Besides what I already have, I also need to validate if the incoming origin and tag fields exist in the collection origins and tags. I've found how to do so when using references but I'm using embedded data so I'm unsure how to exactly do it.
function incomingData() {
return request.resource.data
}
function validTicket() {
return incomingData().email is string &&
incomingData().description is string &&
incomingData().address is string &&
incomingData().location is string &&
incomingData().postCode.matches('^[0-9][0-9][0-9][0-9]-[0-9][0-9][0-9]') &&
incomingData().size() == 5 &&
incomingData().hasAll(['email','description', 'address', 'location', 'postCode']) &&
isSecretary()
}
In the tags collection, every document has a single value with the tag name. The same applies to the origins.
I'm sorry my answer will be partial, i need you to post your current firestore rules, and the name of the ticket collection...
anyway, for tags, you won't be able to search them for their value, and nor inside the rules, so you should save them as keys. that mean, that the key for the document of sports, should be sports, and not 8VCCvq7qnvjyT98r95pu.
next, you will have to use the function exists, in the follow way:
function isTagExists(tag) {
return exists(/databases/$(database)/documents/tags/$(tag));
}
let me know if you updated the question or you need more help with my solution.
also you can read more at:
https://firebase.google.com/docs/firestore/security/rules-conditions
I have a components that based on schema that have a non mandatory metadata field ExtendedType. I can query for a component that have this field with a certain value:
new CustomMetaValueCriteria(new CustomMetaKeyCriteria("ExtendedType"), "Highlight", Criteria.Equal)))
I need to query for a components that have no this field filled in. How can I query for a that.
In SQL I can write next:
select * from t where t.ExtendedType IS NULL
How can i do this using Trdion Query? In common i need to implement query like:
select * from t where t.ExtendedType = "Highlight" OR t.ExtendedType IS NULL
You might be able to achieve this with the NotInCriteria, as follows:
new NotInCriteria
(
new CustomMetaValueCriteria
(
new CustomMetaKeyCriteria("ExtendedType"), "%", Criteria.Like
)
)
I haven't tested this, it's just a thought. Even if it works, be sure to check if it performs as well!
PS: next time, please use the tridion.stackexchange.com forum for Tridion-related questions!
After hours of trying and searching, I think its time to share my problem with you right now.
Problem Definition :
I have a Dictionary of KeyValuePairs(named filterPool) which includes an integer (PropertyID) and a string(McValue). What I am trying to do is filtering products depending on those KeyValuePairs and return them as a DataTable/List.
You may consider this as building dynamic "Where ... And .." clauses as SQL.
Here is the code that I am using :
foreach (KeyValuePair<int, string> filter in filterPool)
{
products = products.Where(i => i.PROPERTYID == filter.Key && i.MCVALUE.Equals(filter.Value));
}
return products.ToDataTable();
The problem is the foreach loop above seems to work only once, for the latest KeyValuePair available in the Dictionary.
As far as I could find on Stackoverflow, the closest solution to my problem was : this one, also using a Dictionary of values for filtering
There must be a way to achieve the goal of filtering using Dictionary and LINQ; or there's a huge thing that I am missing/ignoring to see somehow.
Hope the problem given is clear enough for all,
Thanks
^^
This is a closure issue. You can solve it by making a temporary:
foreach (KeyValuePair<int, string> filterTmp in filterPool)
{
var filter = filterTmp; // Make a temporary
products = products.Where(i => i.PROPERTYID == filter.Key && i.MCVALUE.Equals(filter.Value));
}
return products.ToDataTable();
For details on what's happening, see Eric Lippert's post Closing over the loop variable considered harmful.
Also note that this behavior has changed for C# 5. In C# 5/VS2012, this code would work as expected.
You're overwriting your products collection on every iteration of your foreach. I'm not sure what the data type on your collection is, but you'll want to do something like this in your foreach instead:
products.AddRange(products.Where(i => i.PROPERTYID == filter.Key && i.MCVALUE.Equals(filter.Value)));
I'm not sure if that makes sense, but it seems like you're trying to create a collection full of products that match your filterPool.
I think that it's better solved with aggregate:
return filter
.Aggregate(products, (acc, filter) => acc.Where(i => i.PROPERTYID == filter.Key && i.MCVALUE.Equals(filter.Value)));
.ToDataTable();
I got the following issue. I am trying to use the With or WithMany instruction
to retrieve a linked list of roles of an business relation via an
outer join. The referential integrity is in place on the database but
the primary key on the roles table is a composite key. That's the
reason i use an OuterJoin clause because I get an exception
otherwise .
When the query gets executed the results are exactly as I expected and
nicely filled with data. Nevertheless there are certain cases where
there are not yet roles available in the database. So I would expect
that in those cases the returned SimpleList (Roles below) would be
null, cause there is not data available. Instead Simple.Data returns a
SimpleLIst and if i expand the Dynamic View in debug then it says
'Empty: No further information on this object could be discovered".
Even if i traverse further down and i retrieve the first object in the
SimpleList, it even returns a SimpleRecord with the same information
as above in debug. Only after I request a property of the SimpleRecord
I get some information that the record was empty because then it
returns null.
To come to the bottom line... is there anybody who can tell me how to
check if a SimpleList or SimpleRecord is empty or null without
traversing down the hierarchy?
I am using Simple.Data 0.16.1.0 (due to policy i can't use the
beta yet)
Thanks in advance for reading the whole story...
Below is the code sample:
dynamic businessRelationRoles;
var query = db.Zakenrelaties.As("BusinessRelations")
.All()
.OuterJoin(db.Zakenrelaties_Rollen.As("Roles"), out businessRelationRoles)
.On(zr_ID: db.Zakenrelaties.zr_ID)
.With(businessRelationRoles);
foreach (var relation in query)
{
//Get the SimpleList as IEnumerable
IEnumerable<dynamic> roles = relation.Roles;
//Get the first available SimpleRecord
var role = roles.First();
//Check if any record was returned..This passes always?? Even if the SimpleList was empty
if (role != null)
{
//Get the id of the role. returns null if SimpleRecord was empty
var roleId = role.zrro_id;
}
}
Is there anybody who can help me out?
Belatedly, and for information purposes only, this was a bug and got fixed in the 0.17 (aka 1.0-RC0) release.