I working in a firebase database. I need to limit the length of a string field. How do I do that?
The path to the field is:
Col1/doc1///description
That is, starting with the collection col1, then into doc1, then for all collections under doc1, and all documents under that collection, the description field needs to be limited to 100 characters.
Can someone please explain to me how to do this? Thanks
I tried to get the validation from the other answer to work but was unsuccessful. Firestore just doesn't like checking .length on resource data values.
I searched around and this article helped me:
https://fireship.io/snippets/firestore-rules-recipes/
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /posts/{postId} {
allow read: if true;
allow write: if request.auth != null
&& request.auth.uid == request.resource.data.uid
&& request.resource.data.body.size() > 0
&& request.resource.data.body.size() < 255
&& request.resource.data.title.size() > 0
&& request.resource.data.title.size() < 255;
}
}
}
For Cloud Firestore you can validate that the description field is no longer than 100 characters with:
service cloud.firestore {
match /databases/{database}/documents {
match /col1/doc1 {
allow write: if resource.data.description.length <= 100;
match /subcollection1/{doc=**} {
allow write: if resource.data.description.length <= 100;
}
}
}
}
This applies to col1/doc and all documents in subcollection1. Note that these rules will not limit the length of the description, since security rules cannot modify the data that is written. Instead the rules reject writes where the description is longer than 100 characters.
There is no way (that I know of) to apply rules to each subcollection of only one document. The closest I know is to apply it to all documents and their subcollections:
match /col1/(document=**} {
allow write: if resource.data.description.length <= 100;
}
This applies the validation to all documents in col1 and in all subcollections under that.
Related
Based on my limited searching, it seems GraphQL can only support equal filtering. So,
Is it possible to do Github GraphQL searching with the filtering conditions of,
stars > 10
forks > 3
total commit >= 5
total issues >= 1
open issues <= 60
size > 2k
score > 5
last update is within a year
I.e., filtering will all above conditions. Is it possible?
When querying for repositories, you can apply a filter only for a certain number of the fields in your list:
number of stars
number of forks
size
last update
Although you cannot specify them in the query filter, you can include other fields in your query and verify the values in the client application:
total number of issues
number of open issues
While, in theory, you can also query for the number of commits, applying your specific parameter arguments, that query returns a server error, it most probably times out. For that reason, those lines are commented out.
Here's the GraphQL query:
query {
search(
type:REPOSITORY,
query: """
stars:>10
forks:>3
size:>2000
pushed:>=2018-08-08
""",
last: 100
) {
repos: edges {
repo: node {
... on Repository {
url
allIssues: issues {
totalCount
}
openIssues: issues(states:OPEN) {
totalCount
}
# commitsCount: object(expression: "master") {
# ... on Commit {
# history {
# totalCount
# }
# }
# }
}
}
}
}
}
The specification for repository queries can be found here: https://help.github.com/en/articles/searching-for-repositories#search-by-repository-size
This is not an answer but an update of what I've collected so far.
According to "Select * for Github GraphQL Search", not all above criteria might be available in the Repository edge. Namely, the "total commit", "open issues" and "score" might not be available.
The purpose of the question is obviously to find the valuable repositories and weed off the lower-quality ones. I've collected all the available fields that might be helpful for such assessment here.
A copy of it as of 2018-03-18:
query SearchMostTop10Star($queryString: String!, $number_of_repos:Int!) {
search(query: $queryString, type: REPOSITORY, first: $number_of_repos) {
repositoryCount
edges {
node {
... on Repository {
name
url
description
# shortDescriptionHTML
repositoryTopics(first: 12) {nodes {topic {name}}}
primaryLanguage {name}
languages(first: 3) { nodes {name} }
releases {totalCount}
forkCount
pullRequests {totalCount}
stargazers {totalCount}
issues {totalCount}
createdAt
pushedAt
updatedAt
}
}
}
}
}
variables {
"queryString": "language:JavaScript stars:>10000",
"number_of_repos": 3
}
Anyone can try it out as per here.
This error is super wacky. It doesn't always fail, but when it does it looks like this.
I have some code that changes the "code" (a one character string) of elements in a subdocument array. It goes through each goal, checks to see if there's a change to be applied, and if so, applies it.
for (i = 0; i < user.goals.length; i++) {
if (transformsMap[user.goals[i].code]) {
user.goals[i].code = transformsMap[user.goals[i].code]
}
}
user.goals.sort(function (a,b) {return a.code.charCodeAt(0) - b.code.charCodeAt(0))
When I save it, sometimes I get an error like this:
'goals.3.code':
{ [ValidatorError: Path `code` is required.]
...but 3 in this case, is the length of the goals array. ie there is no goals.3 subdocument. I've tried logging user.goals and user.goals.length right before validation and they both agree that there are only 3 elements in the array.
I am totally baffled.
How about adding more checks? And also setting a default value if the if clause fails?
for (i = 0; i < user.goals.length; i++) {
if (user.goals[i] && user.goals[i].code && transformsMap[user.goals[i].code]){
user.goals[i].code = transformsMap[user.goals[i].code]
} else {
user.goals[i].code = "" // Whatever this is <-- default value.
}
}
user.goals.sort(function (a,b) {return a.code.charCodeAt(0) - b.code.charCodeAt(0))
I am offloading my search feature on a relational database to Azure Search. My Products tables contains columns like serialNumber, PartNumber etc.. (there can be multiple serialNumbers with the same partNumber).
I want to create a suggestor that can autocomplete partNumbers. But in my scenario I am getting a lot of duplicates in the suggestions because the partNumber match was found in multiple entries.
How can I solve this problem ?
The Suggest API suggests documents, not queries. If you repeat the partNumber information for each serialNumber in your index and then suggest based on partNumber, you will get a result for each matching document. You can see this more clearly by including the key field in the $select parameter. Azure Search will eliminate duplicates within the same document, but not across documents. You will have to do that on the client side, or build a secondary index of partNumbers just for suggestions.
See this forum thread for a more in-depth discussion.
Also, feel free to vote on this UserVoice item to help us prioritize improvements to Suggestions.
I'm facing this problem myself. My solution does not involve a new index (this will only get messy and cost us money).
My take on this is a while-loop adding 'UserIdentity' (in your case, 'partNumber') to a filter, and re-search until my take/top-limit is met or no more suggestions exists:
public async Task<List<MachineSuggestionDTO>> SuggestMachineUser(string searchText, int take, string[] searchFields)
{
var indexClientMachine = _searchServiceClient.Indexes.GetClient(INDEX_MACHINE);
var suggestions = new List<MachineSuggestionDTO>();
var sp = new SuggestParameters
{
UseFuzzyMatching = true,
Top = 100 // Get maximum result for a chance to reduce search calls.
};
// Add searchfields if set
if (searchFields != null && searchFields.Count() != 0)
{
sp.SearchFields = searchFields;
}
// Loop until you get the desired ammount of suggestions, or if under desired ammount, the maximum.
while (suggestions.Count < take)
{
if (!await DistinctSuggestMachineUser(searchText, take, searchFields, suggestions, indexClientMachine, sp))
{
// If no more suggestions is found, we break the while-loop
break;
}
}
// Since the list might me bigger then the take, we return a narrowed list
return suggestions.Take(take).ToList();
}
private async Task<bool> DistinctSuggestMachineUser(string searchText, int take, string[] searchFields, List<MachineSuggestionDTO> suggestions, ISearchIndexClient indexClientMachine, SuggestParameters sp)
{
var response = await indexClientMachine.Documents.SuggestAsync<MachineSearchDocument>(searchText, SUGGESTION_MACHINE, sp);
if(response.Results.Count > 0){
// Fix filter if search is triggered once more
if (!string.IsNullOrEmpty(sp.Filter))
{
sp.Filter += " and ";
}
foreach (var result in response.Results.DistinctBy(r => new { r.Document.UserIdentity, r.Document.UserName, r.Document.UserCode}).Take(take))
{
var d = result.Document;
suggestions.Add(new MachineSuggestionDTO { Id = d.UserIdentity, Namn = d.UserNamn, Hkod = d.UserHkod, Intnr = d.UserIntnr });
// Add found UserIdentity to filter
sp.Filter += $"UserIdentity ne '{d.UserIdentity}' and ";
}
// Remove end of filter if it is run once more
if (sp.Filter.EndsWith(" and "))
{
sp.Filter = sp.Filter.Substring(0, sp.Filter.LastIndexOf(" and ", StringComparison.Ordinal));
}
}
// Returns false if no more suggestions is found
return response.Results.Count > 0;
}
public async Task<List<string>> SuggestionsAsync(bool highlights, bool fuzzy, string term)
{
SuggestParameters sp = new SuggestParameters()
{
UseFuzzyMatching = fuzzy,
Top = 100
};
if (highlights)
{
sp.HighlightPreTag = "<em>";
sp.HighlightPostTag = "</em>";
}
var suggestResult = await searchConfig.IndexClient.Documents.SuggestAsync(term, "mysuggestion", sp);
// Convert the suggest query results to a list that can be displayed in the client.
return suggestResult.Results.Select(x => x.Text).Distinct().Take(10).ToList();
}
After getting top 100 and using distinct it works for me.
You can use the Autocomplete API for that where does the grouping by default. However, if you need more fields together with the result, like, the partNo plus description it doesn't support it. The partNo will be distinct though.
Suppose i have 2 records in data base
1) 2007-12-10 10:35:31.000
2) 2008-12-10 10:35:31.000
FirstOrDefault() method will give me the first record match in sequence like 2007-12-10 10:35:31.000 but i need the latest one which is 2008-12-10 10:35:31.000
if ((from value in _names where value != null select value.ExpiryDate < now).Any())
{
return _names.FirstOrDefault();
}
You can use:
return _names.LastOrDefault();
However, your if just sends another unnecessary query (and it is a wrong query too). If you don't have any record, LastOrDefault and FirstOrDefault will return null. You can use something like this to improve the code:
var name = _names.LastOrDefault();
if(name != null)
{
return name;
}
// other code here
If you really want to use FirstOrDefault, you should order descending, like:
var name = _names.Where(n => n.ExpiryDate < now).OrderByDescending(n => n.ExpiryDate).FirstOrDefault();
Given a collection of items { url: 'http://blah' }. How can I tell if a record exists where the url is "http://stackoverflow.com"?
P.s. I am communicating with the c# driver
For any of the previous suggestions to be efficient you should be sure that there is an index on the url element. Otherwise a full collection scan will be required.
If you only expect the answer to be 0 or 1, count is probably the most efficient approach. If you think the count will be very large and all you really care about is whether there is one or more, FindOne is the most efficient approach.
It probably doesn't matter that FindOne returns the whole document unless the document is actually rather large. In that case you could tell the server to only return one field (the _id seems the most likely candidate):
var query = Query.EQ("url", "http://stackoverflow.com");
var fields = Fields.Include("_id");
var res = collection.Find(query).SetFields(fields).SetLimit(1).FirstOrDefault();
if (res == null) {
// no match found
}
you simply need check count of items returned by the query:
int count = collection.FindAs<Item>(Query.EQ("url", "http://stackoverflow.com")).Count();
if(count > 0)
{
//do some stuff
}
IMongoQuery query = Query.EQ("url", "http://stackoverflow.com");
var res = collection.FindOne(query);
if(res == null)//don't exist
{
}
Existence of Key in MongoDB can check by using Exists and second parameter as true or false
var filter = builder.Exists("style", false);
var RetrievedData = collection.Find(filter).ToList()
Refference Link