MongoDB: How to only pull document with exact search term - mongodb

I'm sure this is somewhere on here but I can't seem to find it. I'm trying to pull a document from a large file that only matches an exact term in a field, as opposed to anything with those letters in it.
More precisely, I'm trying to use .find({"name":"Eli"}) to pull the documents with that name, but my search is pulling every name with those letters (such as elizabeth or ophelia)

You can use a regular expression match to make sure you do not return names that share the same character formation.
Something like this:
const name = "Eli"
const query = new RegExp(`^${name}$`)
const user = await Collection.find({ name: { $regex: query } })
I am using 2 key operators from RegEx here: ^ and $
Putting ^ in front of a regular expression will match all strings that start with the pattern given.
Putting $ at the end of a regular expression will match all strings that end with the pattern given.
So essentially you are asking mongoose to find the record where the name both begins and ends with Eli. This will prevent Elizabeth from showing up in your result, but won't filter out other Eli's.

Related

Why is #regex used in task.json in Azure DevOps extension? What does it check for?

I came across this and was wondering what this means and how it works?
What's the significance of using #regex here and how does it expand?
https://github.com/microsoft/azure-pipelines-tasks/blob/master/Tasks/DownloadPackageV0/task.json
"endpointUrl": "{{endpoint.url}}/{{ **#regex ([a-fA-F0-9\\-]+/)[a-fA-F0-9\\-]+ feed }}_apis**/Packaging/Feeds/{{ **#regex [a-fA-F0-9\\-]*/([a-fA-F0-9\\-]+) feed** }}{{#if view}}#{{{view}}}{{/if}}/Packages?includeUrls=false"
Also I would like to know how many packages will it return and display in the Task input UI dropdown if there are thousands of packages in the feed. Is there a known limit like first 100 or something?
#regex doesn't appear to actually be documented anywhere, but it takes two space-delimited arguments. The first is a regular expression and the second is a "path expression" identifying what value to match against, in this case the value of the feed input parameter. If the regex matches the value, it returns the first capturing subexpression, otherwise it returns the empty string.
In this particular context, the feed parameter is formatted as 'projectId/feedId', where projectId and feedId are GUIDs, and projectId and the / are eliminated for organization-scoped feeds (i.e. feeds that are not inside a project). The first regex therefore extracts the project ID and inserts it into the URL, and the second regex extracts the feed ID and inserts it into the URL.
As of this writing, the default limit on the API it's calling is 1000.
Regex stands for regular expression, which allows you to match any pattern rather than an exact string. You can find more info on how to use it in Azure Devops here
This regex is very specific. In this case, the regex ([a-fA-F0-9\\-]+/)[a-fA-F0-9\\-]+\ matches one or more of the following 1) letters a-f (small or capital) Or 2) \ Or 3) - followed by / and then again one or more of those characters.
You can copy the regex [a-fA-F0-9\\-]+/)[a-fA-F0-9\\-]+ into https://regexr.com/ to play around with it, to see what does and doesn't match the pattern.
Examples:
it matches: a/a a/b abcdef-\/dcba
but doesn't match: /a, abcdef, this-doesn't-match
Note that the full endpoint consists of concatenations of both regular expression and hardcoded strings!

How to add bash array variable to mongo update query

I am writing a bash script which updates a mongo document. If it's a new document then it creates a new document in mongo else updates it.
I want to pass bash array variable to the mongo query since few fields are of array type. I am not sure how to pass the array field. Any help would be appreciated.
This is my query:
db.my_col.update({emp_id: '"'$emp_id'"'}, {$set: {contacts: '"'${contacts}'"', emp_name: '"'$emp_name'"'}}, {upsert: true})
If I just add like normal variable the only first value in variable gets added.
If you put your array variable into a string, only the first item will be there, right
Basically, you get all of them with this syntax ${contacts[#]}, but they will be unquoted and separated with spaces and likely won't work in a query because of wrong syntax.
So you'd need to manually convert a Bash array to a JS array. I don't know an automagical way to do it, but consider this function:
function jsarray {
res=""
for a in ${#}; do
res="$res,\"$a\""
done
echo [ ${res:1} ]
}
It goes through it's arguments, wraps each one in quotes and joins together with commas.
Use it like this (I assume $contacts is an array of string values):
IFS=""
contacts=("skype name" "email address" phone website whatever)
jscontacts=$(jsarray $contacts[#])
# Proceed to using $jscontacts in your query.
After that $jscontacts will be a string value of [ "skype name","email address","phone","website","whatever" ].
Notes:
IFS="" - IFS stands for internal field separator, this is how Bash separates arguments from each other. By default it's " " (a space). Resetting it to nothing to preserve array items with spaces in them; otherwise "skype name" beсome two separate values of "skype" & "name".
${res:1} - skips the first character from $res (because it's a comma).
jscontacts=$(...) captures the terminal output into a jscontacts variable.

Microsoft graph Mail Search Strict value

I have an issue with the search parameters. I want to pass a phrase in my query. For exemple i'm looking for emails where the subject is "Test 1".
For this i'm doing a get on this ressource.
https://graph.microsoft.com/v1.0/me/messages?$search="subject:Test 1"
But the behaviour of this query is : Looking for mails that contains "Test" in the subject OR 1 in any other fields.
Refering to the KQL Syntax
A phrase (includes two or more words together, separated by spaces; however, the words must be enclosed in double quotation marks)
So, to do what i want i have to put double quotes (") around my phrase to do a strict value search. Like below
subject:"Test 1"
The problem it's at this point. Microsoft graph api already use double quotes (") after the parameters $search.
?$search="Key words"
So I can't do what is mentioned in the KQL doc.
https://graph.microsoft.com/v1.0/me/messages?$search="subject:"Test 1""
It's throwing an error :
"Syntax error: character '1' is not valid at position 15 in '\"subject:\"test 1\"\"'.",
It's an expected behaviour. I was pretty sure it will not work.
If someone has any suggestions for a solution or a workaround, I'm a buyer.
What I've already tried so far :
Use simple quote
Remove the quotes right after $select=
Remove the subject part $select="Test 1", same behaviour as the first request mentioned in this post. It will looks for emails that contain "test" or "1".
Best regards.
EDIT :
After sasfrog's anwser :
I used $filter : It works well with simple operator AND, OR.I have some errors by using the Not Operator. And btw you have to use the orderby parameter to show the result by date and add the field in filter parameters.
Exemple 1 (working, what I asked for first) :
https://graph.microsoft.com/v1.0/me/messages/?$orderby=receivedDateTime desc &$filter=receivedDateTime ge 1900-01-01T00:00:00Z AND contains(subject,'test 1')
Exemple 2 (not working)
https://graph.microsoft.com/v1.0/me/messages/?$orderby=receivedDateTime desc &$filter=(receivedDateTime ge 1900-01-01T00:00:00Z AND contains(subject,'test 1')) NOT(contains(from/EmailAddress/address,[specific address]))
EDIT 2
After some test with the filter parameters.
The NOT operator is still not working so to workaround use "ne" (non-equals)
the example 2 becomes :
https://graph.microsoft.com/v1.0/me/messages/?$orderby=receivedDateTime desc&$filter=(receivedDateTime ge 1900-01-01T00:00:00Z AND contains(subject,'test 1')) AND (from/EmailAddress/address ne [specific address])
UPDATE : OTHER SOLUTION WITH $search
Using $filter is great but it looks like it was sometimes pretty slow. So I found a workaround aboutmy issue.
It's to use AND operator between all terms.
Exemple 4 :
I'm looking for the mails where the subject is test 1;
Let value = "test 1". So you have to splice it by using space separator. And after write some code to manipulate this array, to obtain something like below.
$search="(subject:test AND subject:1)"
The brackets can be important if you use a multiple fields search. And Voilà.
Not sure if it's sufficient for what you're doing, but how about using the contains function within a filter query instead:
https://graph.microsoft.com/v1.0/me/messages?$filter=contains(subject,'Test 1')
Sounds like you're already looking at the doco but here it is just in case.
Update also, this worked for me using the search method:
https://graph.microsoft.com/v1.0/me/messages?$search="subject:'Test 1'"

getting the path name files in a directory in q

I am using q to get all the files listed in that directory:
key `:Dname
and then try to filter out the the ones that start with numbers as:
key `:Dname like "[0-9]"
but the like part does not quite work. I tried get as well since I like the path to include the directory that the file is in.
Keep in mind that q evaluate expressions from right to left. Your code here will first evaluate
`:Dname like "[0-9]"
and apply key to the result.
You want something closer to
key[`:Dname] like "[0-9]"
But to get what you want you'll have to add a wildcard to the pattern string that you're supplying and apply not to the result
not key[`:Dname] like "[0-9]*"
This will give you a boolean vector, to return the list of files you want use where and index:
key[`:Dname] where not key[`:Dname] like "[0-9]*"
If you have a filename defined like
filename:`2019.01.20file.txt
You can compare this to a pattern using like, similar to what you have done:
filename like "[0-9]*"
"*" is the wildcard symbol which means that anything can come after the [0-9]
like compares a string or symbol to a pattern
So this line return a 1b if the filename starts with a digit between 0 and 9.
Another method would be to compare the start of the filename to .Q.n which is a string of 0-9.
This can be achieved like so:
first[string filename] in .Q.n
string converts the symbol to a string for in to compare it to the string .Q.n
For your situation, I would recommend the first method.
q)key `:q
`README.txt`q.k`q.q`s.k`sp.q`w32
q)key[`:q] like "q*"
011000b
q)x where (x:key[`:q]) like "q*"
`q.k`q.q
q)x where not (x:key[`:q]) like "q*"
`README.txt`s.k`sp.q`w32
This method returns the Boolean list which indicates whether each file starts with "q":
Uses not to reverse the 1s and 0s of this list
Uses where to return the indexes at which the Boolean list is equal to 1
Indexes into key[`:q] with this list
I hope this helps

matlab regexprep

How to use matlab regexprep , for multiple expression and replacements?
file='http:xxx/sys/tags/Rel/total';
I want to replace 'sys' with sys1 and 'total' with 'total1'. For a single expression a replacement it works like this:
strrep(file,'sys', 'sys1')
and want to have like
strrep(file,'sys','sys1','total','total1') .
I know this doesn't work for strrep
Why not just issue the command twice?
file = 'http:xxx/sys/tags/Rel/total';
file = strrep(file,'sys','sys1')
strrep(file,'total','total1')
To solve it you need substitute functionality with regex, try to find in matlab's regexes something similar to this in php:
$string = 'http:xxx/sys/tags/Rel/total';
preg_replace('/http:(.*?)\//', 'http:${1}1/', $string);
${1} means 1st match group, that is what in parenthesis, (.*?).
http:(.*?)\/ - match pattern
http:${1}1/ - replace pattern with second 1 as you wish to add (first 1 is a group number)
http:xxx/sys/tags/Rel/total - input string
The secret is that whatever is matched by (.*?) (whether xxx or yyyy or 1234) will be inserted instead of ${1} in replace pattern, and then replace instead of old stuff into the input string. Welcome to see more examples on substitute functionality in php.
As documented in the help page for regexprep, you can specify pairs of patterns and replacements like this:
file='http:xxx/sys/tags/Rel/total';
regexprep(file, {'sys' 'total'}, {'sys1' 'total1'})
ans =
http:xxx/sys1/tags/Rel/total1
It is even possible to use tokens, should you be able to define a match pattern for everything you want to replace:
regexprep(file, '/([st][yo][^/$]*)', '/$11')
ans =
http:xxx/sys1/tags/Rel/total1
However, care must be taken with the first approach under certain circumstances, because MATLAB replaces the pairs one after another. That is to say if, say, the first pattern matches a string and replaces it with something that is subsequently matched by a later pattern, then that will also be replaced by the later replacement, even though it might not have matched the later pattern in the original string.
Example:
regexprep('This\is{not}LaTeX.', {'\\' '([{}])'}, {'\\textbackslash{}' '\\$1'})
ans =
This\textbackslash\{\}is\{not\}LaTeX.
=> This\{}is{not}LaTeX.
and
regexprep('This\is{not}LaTeX.', {'([{}])' '\\'}, {'\\$1' '\\textbackslash{}'})
ans =
This\textbackslash{}is\textbackslash{}{not\textbackslash{}}LaTeX.
=> This\is\not\LaTeX.
Both results are unintended, and there seems to be no way around this with consecutive replacements instead of simultaneous ones.