How to write regex in elasticsearch "URI Search" style - regex

I want to query Elasticsearch using the "URI Search" format (https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html#search-uri-request) with a regex but cannot find out how to deal with regex special characters symbols like \s and the simple space.
Let's say I have the term [ apple computer ] stored in my index (keyword analyzer used).
the term will be found with :
curl -XGET http://es:9200/myindex/mytype/_search?q=name:/.*comp.*/&pretty
curl -XGET http://es:9200/myindex/mytype/_search?q=name:/.*appl.*/&pretty
curl -XGET http://es:9200/myindex/mytype/_search?q=name:/.*pple.*/&pretty
but what syntax should I use (in curl, or with another tool) to query using these regex :
/.*pple\s+compu.*/
/.*le +compu.*/

I think I've found the asnwer to my question:
First with my index setting being like this, I need to use name.keyword for a full text search
{
"myindex" : {
"aliases" : { },
"mappings" : {
"mytype" : {
"properties" : {
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
...
Then, doing a query using the "URI Search" format I have to use the tipycal conversion
a space should be written as +
+ should be written as %2b
anyother special characters in a url should be written with its %ASCII equivalent
so it turns out my regular expression /.*le +compu.*/ must be queried like that :
curl -XGET "http://es:9200/myindex/mytype/_search?q=name.keyword:/.*pple+%2bcomp.*/&pretty"
Finally, I can't see in the regexp doc or lucene any mention of the \s symbol as a wildcard for space, but not a big deal as it can be rewritten using regexp sub-patterns.

Related

How to extract a double quote field in regex that start with a specific string

I'd like to extract the name content (David) and the url content (www.stackoverflow.com) from the following json file.
I have several questions:
How to extract a string that starts with " and ends with " ?
Hoe to force the regular expression to start with an expression that is not part of the matching regular expressing.
{
"id" : "1234",
"name" : "David",
"request" : {
"url" : "www.stackoverflow.com",
"method" : "POST",
"bodyPatterns" : [ {
"matchesXPath" : "example"
}, {
"matchesXPath" : "example/123"
}, {
"matchesXPath" : {
"expression" : "example/123/123/text()",
"equalTo" : "bbbb"
}
} ]
}
}
Note: a proper parser is the most recommended way to do this on the long term. For a simple, occasional situation regex might fit.
This regex does the job:
"name"\s*:\s*"(?'name'[^"]+)".*"url"\s*:\s*"(?'url'[^"]+)"
Test here. Groups name and url contain your data.
I do not recommend solving this with a regular expression. Such ad-hoc parsing solutions tend to be error-prone, overly complicated, hard to extend and turn on you when you least expect it.
Instead, I recommend using a proper json parser, depending on the language you use. For plain shell, jq is a good choice. With that, specifying the path to the property becomes trivial:
cat file.json | jq '.request.url'

MongoDB regex matching trouble

Here is my MongoDB shell session;
> db.foo.save({path: 'a:b'})
WriteResult({ "nInserted" : 1 })
> db.foo.findOne()
{ "_id" : ObjectId("58fedc47622e89329d123ee8"), "path" : "a:b" }
> db.foo.save({path: 'a:b:c'})
WriteResult({ "nInserted" : 1 })
> db.foo.find({path: /a:[^:]+/})
{ "_id" : ObjectId("58fedc47622e89329d123ee8"), "path" : "a:b" }
{ "_id" : ObjectId("58fedc57622e89329d123ee9"), "path" : "a:b:c" }
> db.foo.find({path: /a:[a-z]+/})
{ "_id" : ObjectId("58fedc47622e89329d123ee8"), "path" : "a:b" }
{ "_id" : ObjectId("58fedc57622e89329d123ee9"), "path" : "a:b:c" }
Clearly the regex /a:[^:]+/ and /a:[a-z]+/ shouldn't match string 'a:b:c', but looks like Mongo failed on this regex, does anyone know what happened here?
It was submitted to MongoDB Jira, as a bug ticket, so is it a bug within MongoDB querying structure?
The trouble is with the partial matching, since you are not restricting the regex for the whole word, the partial match that exists in a:b:c that is a:b is resulting in you getting that document.
Use the following regex with ^$ that are anchors to represent beginning and the end of the word;
db.foo.find({path: /^a:[^:]+$/})
db.foo.find({path: /^a:[a-z]+$/})
This will make the regex apply for the whole string, and ignore the partial matches as explained above. For more on regex anchors, click here.
So, in summary, there is no bug, just a misuse of regex.

Multiple conditions in mongo regex query

I want to match all documents where Url field in db contains both should and match, in any order.
In example, those should match:
http://www.myurl.com/should/match
http://www.myurl.com/match/should
But not http://www.myurl.com/no/match
I tried several regex, but no match. I.e:
db.mycollection.find({"Url":/^(?=.*\should\b)(?=.*\match\b).*$/})
Returns no matches.
Appreciate any help.
Best Regards
Set the beginning boundaries of those words in your regex with \b as you have set the ending boundaries
db.mycollection.find( { "Url": /^(?=.*\bshould\b)(?=.*\bmatch\b).*$/ } )
On collection of documents
{ "Url" : "http://www.myurl.com/should/match" }
{ "Url" : "http://www.myurl.com/match/should" }
{ "Url" : "http://www.myurl.com/no/match" }
it returns
{ "Url" : "http://www.myurl.com/should/match" }
{ "Url" : "http://www.myurl.com/match/should" }

Finding documents through regex in Mongo

I have a document structure like this one.
> db.urls.find()
{
"_id" : ObjectId("53d79c7020ba271c80b78b6c"),
"url" : "http://www.newstoday.com.bd?option=details&news_id=2368296&date=2014-01-27///",
"priority" : 0.25,
"date" : ISODate("2014-07-29T13:06:58.745Z"),
"seen" : 1
}
To find some document using regex I used the following,
> db.urls.find({url: { $regex: 'http://www.newstoday.com.bd?option='} })
>
Which resulted empty. I need some help on the proper regex to use here.
(?=.*?http:\/\/www\.newstoday\.com\.bd\?.*)(.*)
This will give the document based on the url if that is what you are looking for.
See Demo.
http://regex101.com/r/wE3dU7/1

sed - trying to replace first occurrence after a match

I am facing a situation that drives me nuts.
I am setting up an update server which uses a json file.
Don't ask why or how, it sucks and is my only possibility to achieve it.
I have been trying and researching for HOURS (many) because I went ballistic and wanted to crack this on my own. But I have to realize I got stuck and need help.
So sorry for this chunk but I think it is somewhat important to see...
The file is a one liner and repeating the following sequence with changing values (of course).
"plugin_name_foo_bar": {"buildDate": "bla", "dependencies": [{"name": "bla", "optional": true, "version": "1.00"}], "developers": [{"developerId": "bla", "email": "bla#gmail.com", "name": "Bla bla2nd"}], "excerpt": "some text {excerpt} !bla.png|thumbnail,border=1! ", "gav": "bla", "labels": ["report", "scm-related"], "name": "plugin_name_foo_bar", "previousTimestamp": "bla", "previousVersion": "1.0", "releaseTimestamp": "bla", "requiredCore": "1", "scm": "github.com", "sha1": "ynnBM2jWo25ZLDdP3ybBOnV/Pio=", "title": "bla", "url": "http://bla.org", "version": "1.0", "wiki": "https://bla.org"}, "Exclusion": {"buildDate": "bla", "dependencies": [],
and the next plugin block is glued straight afterwards.
What I now want to do is to search for "plugin_foo_bar": {" as this is the unique identifier for a new plugin description block.
I want to replace the first sha1 value occuring afterwards. That's where I keep failing. I always grab the first,last or any occurrence in the entire file and not the block :(
"title" is the unique identifier after the sha1 value.
So I tried to make the .* less greedy but it ain't working out.
last attempt was heading towards:
sed -i 's/("name": "plugin_name_foo_bar.*sha1": ")([a-zA-Z0-9!##\$%^&*()\[\]]*)(", "title"\)/\1blablabla\2/1' default.json
to find the sha1 value of that plugin but still no joy. I hope someone knows - preferably a simpler approach - before I now continue with trial and error until I have to puke and freakout.
I am working with SED on Windows, so Unix approach might help me to figure out how to achieve this in batch but please make it as one-liner if possible. Scripts are a real pain to convert.
And I just need SED and no other solution with other tools like AWK. That is absolutely out of discussion.
Any help is appreciated :)
Cheers
Jan
Don't use regex (sed) to parse JSON, instead use a proper JSON parser, or javascript directly like I do :
Using javascript and nodejs in a script :
File /tmp/file.json is :
{
"plugin_name_foo_bar" : {
"excerpt" : "some text {excerpt} !bla.png|thumbnail,border=1! ",
"dependencies" : [
{
"name" : "bla",
"version" : "1.00",
"optional" : true
}
],
"title" : "bla",
"previousTimestamp" : "bla",
"releaseTimestamp" : "bla",
"sha1" : "ynnBM2jWo25ZLDdP3ybBOnV/Pio=",
"labels" : [
"report",
"scm-related"
],
"buildDate" : "bla",
"version" : "1.0",
"previousVersion" : "1.0",
"name" : "plugin_name_foo_bar",
"scm" : "github.com",
"url" : "http://bla.org",
"gav" : "bla",
"developers" : [
{
"email" : "bla#gmail.com",
"developerId" : "bla",
"name" : "Bla bla2nd"
}
],
"wiki" : "https://bla.org",
"requiredCore" : "1"
},
"Exclusion" : {
"dependencies" : [],
"buildDate" : "bla"
}
}
The script script.js :
var js = require('/tmp/file.json')
js.plugin_name_foo_bar.sha1 = "xxx"
console.log(js)
Usage :
nodejs script.js
As sputnick points out parsing is a little beyond what sed's meant for. Still, sed's Turing-complete and bludgeoning it into doing what you want can satisfy that {sad,masoch}istic urge so many of us feel from time to time.
This one's even easy.
sed '
s/"sha1": /\n/g
s/\("name": "plugin_name_foo_bar"[^\n]*\n"\)[^"]*/\1thenewsha/
s/\n/"sha1": /g
'
For windows command line, with escaped quotes, replacing inline and using regular expression
sed -i -r "s/(plugin_name_foo_bar.+?sha1\": \")[^\"]+\"/\1abcdefghijkl\"/" default.json
sed -r "s/(plugin_name_foo_bar[^!]+sha1.: .)[^\"]+/\1abcdefghijkl/" file