An Elastic document has a structure like this:
...
"somefield": "somevalue",
"orders": [{
"version": 1,
"statusCode": 1
}, {
"version": 1,
"statusCode": 1
}, {
"version": 2,
"statusCode": 2
}, {
"version": 3,
"statusCode": 5
}, {
"version": 3,
"statusCode": 6
}
]
...
"orders" is a nested list. I use inline sctipting to calculate the size of the list like this:
"params._source.orders.size() < 4"
I have to add a condition to calculate the number of orders whose statusCode is not 5 and not 6. Linq would look like this:
...orders.Where(o=>!(new[] {5, 6}).Contains(o.statusCode)).size()...
How to write the script in Painless or Groovy?
This results an exeption:
params._source.orders.count { it -> it.statusCode == 1 } < 4
I have found one of the solutions in Painless:
def count = 0;
for (item in params._source.orders){
if (item.statusCode != 5 && item.statusCode != 6) {
count++; }}
return count < 4;
Related
It is possible to make a search by the results of another search?. For example:
// index: A
{ "ID": 1, "status": "done" }
{ "ID": 2, "status": "processing" }
{ "ID": 3, "status": "done" }
{ "ID": 4, "status": "done" }
// index: B
{ "ID": 1, "user": 1, "value": 10 }
{ "ID": 1, "user": 2, "value": 3 }
{ "ID": 2, "user": 1,"value": 1 }
{ "ID": 3, "user": 1, "value": 3 }
{ "ID": 4, "user": 1, "value": 7 }
Q1: Search in index "A" status == "done" and return the ID
RES: 1,3,4
Q2: From the results in Q1 search value > 5 and return the ID
RES: 1,4
My current solution is use two queries and download the results of "Q1" and make a second search in "Q2" but is very complicated because have 30k of results.
the problem to me seems to be more of a traditional union of filters in 2 indexes sort of a join , what we have in relational databases , not sure of the exact solution but recently had used a plug-in for the joins -> https://siren.io/siren-federate-20-0-introducing-a-scalable-inner-join-for-elasticsearch/ this might help
I am working on a project where I have to create one to many relationships which will get all the list of records referenced by id in another table and I have to display all the selected data in the multi-select field (selectArrayInput). Please help me out in this, if you help with an example that would be great.
Thanks in advance.
Example:
district
id name
1 A
2 B
3 C
block
id district_id name
1 1 ABC
2 1 XYZ
3 2 DEF
I am using https://github.com/Steams/ra-data-hasura-graphql hasura-graphql dataprovider for my application.
You're likely looking for "nested object queries" (see: https://hasura.io/docs/1.0/graphql/manual/queries/nested-object-queries.html#nested-object-queries)
An example...
query MyQuery {
district(where: {id: {_eq: 1}}) {
id
name
blocks {
id
name
}
}
}
result:
{
"data": {
"district": [
{
"id": 1,
"name": "A",
"blocks": [
{
"id": 1,
"name": "ABC"
},
{
"id": 2,
"name": "XYZ"
}
]
}
]
}
}
Or...
query MyQuery2 {
block(where: {district: {name: {_eq: "A"}}}) {
id
name
district {
id
name
}
}
}
result:
{
"data": {
"block": [
{
"id": 1,
"name": "ABC",
"district": {
"id": 1,
"name": "A"
}
},
{
"id": 2,
"name": "XYZ",
"district": {
"id": 1,
"name": "A"
}
}
]
}
}
Setting up the tables this way...
blocks:
districts:
Aside: I recommend using plural table names as they are more standard, "districts" and "blocks"
I need help to sort array by couple of logics
[
{
"id": 1,
"status": "pending",
"date": "2019-08-01"
},
{
"id": 2,
"status": "delivered",
"date": "2019-08-01"
},
{
"id": 3,
"status": "pending",
"date": "2019-08-03"
},
{
"id": 4,
"status": "delivered",
"date": "2019-08-03"
},
{
"id": 5,
"status": "delivered",
"date": "2019-08-02"
}
]
what I want to do is to sort the array to status pending show first, and then sort it by the date descending
I already test to using sortByDesc from laravel collection but the array looks like sorted it by just 1 function
$collection = $collection->sortByDesc('date')->sortByDesc(function ($row, $key) {
if($row['status'] == 'pending'){
return 1;
}else{
return 0;
}
});
My expected final result look like this :
[
{
"id": 3,
"status": "pending",
"date": "2019-08-03"
},
{
"id": 1,
"status": "pending",
"date": "2019-08-01"
},
{
"id": 4,
"status": "delivered",
"date": "2019-08-03"
},
{
"id": 5,
"status": "delivered",
"date": "2019-08-02"
},
{
"id": 2,
"status": "delivered",
"date": "2019-08-01"
}
]
Few solutions:
Use a custom callback and return an array source
$products->sortBy(function($product) {
return [$product->param1, $product->param2];
});
This will sort a collection by param2 first, and then by param1
Use a custom callback and return a composite property to sort on source
$posts = $posts->sortBy(function($post) {
return sprintf('%-12s%s', $post->column1, $post->column2);
});
Sort your array by column 1, then split it up by column 2 and then merge it again (untested).
$collection->sortByDesc('date');
$collection->groupBy('status');
$collection->keyBy('status');
EDIT: Also I'm not sure if sortByDesc('date') works with date strings.
Your expected result can be achieved like this.
$sorted = $collection
->sortByDesc('date')
->sortBy(function ($item) {
return 'pending' == $item['status'] ? 0 : 1;
})
->values();
To be more precise:
$collection= $collection->sort(
function ($a, $b) {
if(($a->status== $b->status) &&($a->status== 'pending')){
return ($a->date >= $b->date) ? -1 : 1;
}elseif($a->status== 'pending' && ($a->status!= $b->status)){
return 1;
}else{
return ($a->date <= $b->date) ? 1 : -1;
}
}
);
$collection= $collection->sortByDesc('status');
I have a query that uses group() function:
...group('a','b','c','na').count()
the now the result is returns like in the form of group and reduction like this:
How can I get result without group and reduce in the form of
{
"na": 1285
"c" : 487
"b" : 746
"a" : 32
}
I'm not sure, but I think you're misunderstanding what group does.
The group command takes a property and groups documents by that property. So, for example, if you wanted to group documents by the a property, that would look something like this:
{
a: 1
}, {
a: 1
}, {
a: 1
}, {
a: 2
}
Then you would run the following query:
r.table(...).group('a').count().ungroup()
Which would result in:
[
{
"group": 1 ,
"reduction": 3
},
{
"group": 2 ,
"reduction": 1
}
]
By passing multiple arguments to group you are telling it to make distinct groups for all those properties. So you you have the following documents:
[ {
a: 1, b: 1
}, {
a: 1, b: 1
}, {
a: 1, b: 2
}, {
a: 2, b: 1
}]
And you group them by a and b:
r.table(...).group('a', 'b').count().ungroup()
You will get the following result:
[{
"group": [ 1 , 1 ] ,
"reduction": 2
},
{
"group": [ 1 , 2 ] ,
"reduction": 1
},
{
"group": [ 2 , 1 ] ,
"reduction": 1
}]
Your Answer
So, when you do .group('a','b','c','na').count(), you're grouping them by those 4 properties. If you want the following result:
{
"na": 1285
"c" : 487
"b" : 746
"a" : 32
}
Then your documents should look something like this:
[{
property: 'a'
}, {
property: 'c'
}, {
property: 'na'
},
...
]
And then you would group them in the following way:
r.table(...).group('property').count().ungroup()
Let's say I have the following array
var data = [{ id: 0, points: 1 }, { id: 1, points: 2 }]
I would like to update my table which contains
{
"doc-1": {
"id": "abcxyz123",
"entries": [
{ "id": 0, "points": 5 },
{ "id": 1, "points": 3 },
{ "id": 2, "points": 0 }
]
}
}
so that I add the points-field in the data array to the points-field for each element in the "entries" array in "doc-1" that matches the corresponding id in the data array. The end result would look like:
{
"doc-1": {
"id": "abcxyz123",
"entries": [
{ "id": 0, "points": 6 },
{ "id": 1, "points": 4 },
{ "id": 2, "points": 0 }
]
}
}
How do I go about to write such a query in ReQL?
I assume that the actual document in the table looks like this for now:
{
"id": "abcxyz123",
"entries": [{
"id": 0,
"points": 5
}, {
"id": 1,
"points": 3
}, {
"id": 2,
"points": 0
}]
}
That is without the doc-1 nesting.
Then your update can be done like this:
r.table('t1').update(
{
entries: r.row('entries').map(function(e) {
return r.do(r.expr(data)('id').indexesOf(e('id')), function(dataIndexes) {
return r.branch(
dataIndexes.isEmpty(),
e,
{
id: e('id'),
points: e('points').add(r.expr(data)(dataIndexes(0))('points'))
});
});
})
})
I'm using map to map over each entry in entries, and indexesOf to find the corresponding entry in data if it exists.
Note that this doesn't add new entries to the entries list, but only updates existing ones. Please let me know if you need to add new entries as well.
If your documents actually have the doc-1 field first, this query should do the job:
r.table('t1').update(
{ 'doc-1':
{
entries: r.row('doc-1')('entries').map(function(e) {
return r.do(r.expr(data)('id').indexesOf(e('id')), function(dataIndexes) {
return r.branch(
dataIndexes.isEmpty(),
e,
{
id: e('id'),
points: e('points').add(r.expr(data)(dataIndexes(0))('points'))
});
});
})
}
})