Pattern Match on String Column - azure-log-analytics

In many functional programming languages there is a way to do pattern matching, like F# has match expression with.
In my use case, I'd like to match a string to a set of strings/regexes and returning a value(a string):
// path:string
iif(path == '/', 'home',
iif(path == '/search', 'search',
iif(path == '/*/*/*-for-sale-*', 'product',
'other',
)))
The iif syntax is really ugly though. Is there a more concise way to find a string match and return a value?

There is a relatively new syntax for case():
range Size from 1 to 15 step 2
| extend bucket = case(Size <= 3, "Small",
Size <= 10, "Medium",
"Large")

Related

How to write a CASE clause with another column as a condition using knex.js

So my code is like one below:
.select('id','units',knex.raw('case when units > 0 then cost else 0 end'))
but it gives me error like this one
hint: "No operator matches the given name and argument type(s). You might need to add explicit type casts."
Any idea how I should right my code so I can use another column as an condition for different to column ?
I don't get the same error you do:
CASE types integer and character varying cannot be matched
but regardless, the issue is that you're trying to compare apples and oranges. Postgres is quite strict on column types, so attempting to put an integer 0 and a string (value of cost) in the same column does not result in an implicit cast.
Turning your output into a string does the trick:
.select(
"id",
"units",
db.raw("CASE WHEN units > 0 THEN cost ELSE '0' END AS cost")
)
Sample output:
[
{ id: 1, units: null, cost: '0' },
{ id: 2, units: 1.2, cost: '2.99' },
{ id: 3, units: 0.9, cost: '4.50' },
{ id: 4, units: 5, cost: '1.23' },
{ id: 5, units: 0, cost: '0' }
]

Filtering dstore collection against an array field

I'm trying to filter a dstore collection by a field that has an array of values. My json data looks like the following (simplified):
[{
user_id: 1,
user_name: "John Doe",
teams: [{team_id: 100, team_name: 'Red Sox'}, {team_id: 101, team_name: 'Buccaneers'}]
},
{
user_id: 2,
user_name: "Fred Smith",
teams: [{team_id: 100, team_name: 'Buccaneers'}, {team_id: 102, team_name: 'Rays'}]
}]
I can do a simple filter against the username field and it works perfectly.
this.dstoreFilter = new this.dstore.Filter();
var results = this.dgrid.set('collection', this.dstore.filter(
this.dstoreFilter.match('user_name',new RegExp(searchTerm, 'i'))
));
How, though, do I construct a filter to show me only those players who play for the Red Sox, for example. I've tried using the filter.contains() method, but I can't find any adequate documentation on how it works. Looking at the dstore code, I see that the filter.contains() method has the following signature: (value, required, object, key), but that's not helping me much.
Any guidance would be much appreciated. Thanks in advance!
You can find documentation on Filtering here.
In your case, .contains() will not work because it is intended to work on values of array type. What you want to filter here is array of objects. Here is a quote from the doc link:
contains: Filters for objects where the specified property's value is an array and the array contains any value that equals the provided value or satisfies the provided expression.
In my opinion, the best way here is to override the filter method where you want to filter by team name. Here is some sample code:
this.grid.set('collection', this.dstore.filter(lang.hitch(this, function (item) {
var displayUser = false;
for(var i=0; i < item.teams.length; i++){
var team = item.teams[i];
if(team.team_name == 'Red Sox'){
displayUser = true;
break;
}
}
return displayUser;
})));
this.grid.refresh();
For each user in the store, if false is returned, it's display is set to false and if true is returned it gets displayed. This is by far the easiest way that I know of to apply complex filtering on dstore.
Some similar questions that you might want to read up: link, link, link

MongoDB like statement with multiple fields

With SQL we can do the following :
select * from x where concat(x.y ," ",x.z) like "%find m%"
when x.y = "find" and x.z = "me".
How do I do the same thing with MongoDB, When I use a JSON structure similar to this:
{
data:
[
{
id:1,
value : "find"
},
{
id:2,
value : "me"
}
]
}
The comparison to SQL here is not valid since no relational database has the same concept of embedded arrays that MongoDB has, and is provided in your example. You can only "concat" between "fields in a row" of a table. Basically not the same thing.
You can do this with the JavaScript evaluation of $where, which is not optimal, but it's a start. And you can add some extra "smarts" to the match as well with caution:
db.collection.find({
"$or": [
{ "data.value": /^f/ },
{ "data.value": /^m/ }
],
"$where": function() {
var items = [];
this.data.forEach(function(item) {
items.push(item.value);
});
var myString = items.join(" ");
if ( myString.match(/find m/) != null )
return 1;
}
})
So there you go. We optimized this a bit by taking the first characters from your "test string" in each word and compared the tokens to each element of the array in the document.
The next part "concatenates" the array elements into a string and then does a "regex" comparison ( same as "like" ) on the concatenated result to see if it matches. Where it does then the document is considered a match and returned.
Not optimal, but these are the options available to MongoDB on a structure like this. Perhaps the structure should be different. But you don't specify why you want this so we can't advise a better solution to what you want to achieve.

Dojo DGrid RQL Search

I am working with a dgrid where I want to find a search term in my grid on two columns.
For instance, I want to see if the scientific name and commonName columns contain the string "Aca" (I want my search to be case insensitive)
My Grid definition:
var CustomGrid = declare([Grid, Pagination ]);
var gridStore = new Memory({ idProperty: 'tsn', data: null });
gridStore.queryEngine = rql.query;
grid = new CustomGrid({
store: gridStore,
columns:
[
{ field: "tsn", label: "TSN #"},
{ field: "scientificName", label: "Scientific Name"},
{ field: "commonName", label: "Common Name",},
],
autoHeight: 'true',
firstLastArrows: 'true',
pageSizeOptions: [50, 100],
}, id);
With the built in query language (I think simple query language), I was able to find the term in one column or the other, but I couldn't do a complex search that would return results for both columns.
grid.set("query", { scientificName : new RegExp(speciesKeyword, "i") });
grid.refresh()
I started reading and I think RQL can solve this problem, however, I am struggling with the syntax.
I have been looking at these pages:
http://rql-engine.eu01.aws.af.cm/
https://github.com/kriszyp/rql
And I am able to understand basic queries, however the "contains" syntax eludes me.
For instance if I had this simple data set and wanted to find the entries with scientific and common names that contain the string "Aca" I would think my contains query would look like this:
contains(scientificName,string:aca)
However, this results in no matches.
[
{
"tsn": 1,
"scientificName": "Acalypha ostryifolia",
"commonName": "Rough-pod Copperleaf",
},
{
"tsn": 2,
"scientificName": "Aegalius acadicus",
"commonName": "Northern Saw-whet Owl",
},
{
"tsn": 3,
"scientificName": "Portulaca pilosa",
"commonName": "2012-02-01",
},
{
"tsn": 4,
"scientificName": "Accipiter striatus",
"commonName": "Kiss-me-quick",
},
{
"tsn": 5,
"scientificName": "Acorus americanus",
"commonName": "American Sweetflag",
}
]
Can someone guide me in how to formulate the correct syntax? Thank you.
From what I'm briefly reading, it appears that:
contains was replaced by any and all
these are meant for array comparisons, not string comparisons
I'm not sure offhand whether RegExps can just be handed to other operations e.g. eq.
With dojo/store/Memory, you can also pass a query function which will allow you to do whatever you want, so if you wanted to compare for a match in one field or the other you could do something like this:
grid.set('query', function (item) {
var scientificRx = new RegExp(speciesKeyword, 'i');
var commonRx = new RegExp(...);
return scientificRx.test(item.scientificName) || commonRx.test(item.commonName);
});
Of course, if you want to filter only items that match both, you can do that with simple object syntax:
grid.set('query', {
scientificName: scientificRx,
commonName: commonRx
});

Best way to parse a query like string

So I am building a query like search component for a web application I am working on, similar to the search bar seen for Jira's advance issues search:
https://jira.atlassian.com/browse/WBS-167?jql=status%20%3D%20Accepted
The search is basically very similar to the WHERE statement in SQL but only supporting selected set of comparison operators (for instance I don't plan on supporting the between comparison operator). First thing that came to mind is to use regex but I hear that SQL is the 3rd worst thing to parse with regex.
As an example, this would probably be a complex query I would want to be able to parse:
firstName = 'john' OR (lastName = 'doe' AND (status IN (1,3,5) OR type NOT IN (2, 4, 6)) AND username CONTAINS 'd' AND (type = 1 OR status = 2)
and would would want the result of parsing this string to looks something like this:
[{
field: 'firstName',
comparison: '=',
value: 'john'
}, {
connector: 'OR',
items: [{
field: 'lastName',
comparison: '=',
value: 'doe'
}, {
connector: 'AND',
items: [{
field: 'status',
comparison: 'IN',
value: [1,3,5]
}, {
connector: 'OR',
field: 'type',
comparison: 'NOT IN',
value: [2,4,6]
}]
}]
}, {
connector: 'AND',
field: 'username',
comparison: 'CONTAINS',
value: 'd'
}, {
connector: 'AND',
items: [{
field: 'type',
comparison: '=',
value: 1
}, {
connector: 'OR',
field: 'status',
comparison: '=',
value: 2
}]
}]
If regex is a bad choice (and trying to work with regex for a couple of hours did not produce any good results), what is the best why to try to parse this type of string?
It looks like you are developing a small and simple language. As ebyrod said you should use a grammar-based parser instead of regex. Lex and Yacc are great and easy tools for the job. Depending on the language you are using, there are different alternatives.
Take a look at this.
As you can see, you will need to define all the supported operations that can appear on your input. This is done on the Lex file. Then you will need to define your syntax structure (grammar) and the last step is composing your output string.