ElasticSearch using decay functions when a date range matches - elasticsearch

I'm currently trying to set up a search where a user can search for room bookings with a degree of fuzziness, i.e. when there are no exact matches, the user sees results that have availabilty around that date. In my document, a bed has a premises and multiple bookings like so:
{
"bed": {
....
"premises": {
....
},
"bookings": [
{
date_from: "2020-01-02",
date_to: "2020-02-22"
},
....
]
}
}
I've attempted to add a function_score to my query as follows:
{
gauss: {
'bookings.start_time': {
origin: this.filterArgs.date_from,
scale: '10d',
offset: '2d',
},
'bookings.end_time': {
origin: this.filterArgs.date_to,
scale: '10d',
offset: '2d',
},
},
}
But it seems that this prioritises beds with bookings that match that date. Is there any way to do the inverse of this - i.e. prioritise the beds with no bookings for a given date range?
Any help would be appreciated!
Edit: Here's my index mapping:
{
mappings: {
properties: {
premises: {
properties: {
location: {
type: 'geo_point',
},
},
},
bookings: {
properties: {
start_time: {
type: 'date',
},
end_time: {
type: 'date',
},
},
},
},
},
}

Related

Sorting on nested object in elastic search, failed to find nested object under path

I have the following 2 documents indexed.
{
region: 'US',
manager: {
age: 30,
name: {
first: 'John',
last: 'Smith',
},
},
},
{
region: 'US',
manager: {
age: 30,
name: {
first: 'John',
last: 'Cena',
},
},
}
I am trying to search and sort them by their last name. I have tried the following query.
{
sort: [
{
'manager.name.first': {
order: 'desc',
nested: {
path: 'manager.name.first',
},
},
},
],
query: {
match: {
'manager.name.first': 'John',
},
},
},
I am getting the following error in response. What am I doing wrong here (I am very new to this elasticsearch, so apologize if this is a very basic thing I am not aware of)
ResponseError: search_phase_execution_exception: [query_shard_exception] Reason: [nested] failed to find nested object under path [manager.name.first]
I also tried path: 'manager.name', but that also didn't work.
You need to use only manager as nested path as that is only field define as nested type.
{
"sort": [
{
"manager.name.first.keyword": {
"order": "desc",
"nested": {
"path": "manager"
}
}
}
]
}
Use manager.name.first as field name if it is defined as keyword type otherwise use manager.name.first.keyword if it is define as multi type field with text and keyword both.

filtering out zero total from nested result in graphql query

I have the following query that can be run against the github graphql API
query userRepositories($cursor: String, $q: String!, $githubId: String!) {
search(query: $q, type: REPOSITORY, first: 100, after: $cursor) {
repositoryCount
pageInfo {
endCursor
startCursor
}
nodes {
... on Repository {
id
name
description
isArchived
isPrivate
nameWithOwner
url
defaultBranchRef {
target {
... on Commit {
history(first: 10, author: {id: $githubId}) {
totalCount
}
}
}
}
}
}
}
}
It returns results like this:
{
"data": {
"search": {
"repositoryCount": 103,
"pageInfo": {
"endCursor": "Y3Vyc29yOjEwMA==",
"startCursor": "Y3Vyc29yOjE="
},
"nodes": [
{
"id": "MDEwOlJlcG9zaXRvcnk2MTg1OTczOA==",
"name": "microstates",
"nameWithOwner": "thefrontside/microstates",
"url": "https://github.com/thefrontside/microstates",
"defaultBranchRef": {
"target": {
"history": {
"totalCount": 0
}
}
},
{
"id": "MDEwOlJlcG9zaXRvcnkxNTU5MTUyODc=",
"name": "effection",
"nameWithOwner": "thefrontside/effection",
"url": "https://github.com/thefrontside/effection",
"defaultBranchRef": {
"target": {
"history": {
"totalCount": 16
}
}
}
},
I am only interested in the nodes array that has a defaultBranchRef.target.history.totalCount that is greater than 0.
So I am not interested in element 0 of the nodes array but I am of element 1.
Can I filter this in graphql or do I have to do that in code outside of the query?
GraphQL can't filter an array so if the API support filter base on totalCount you can pass this filter otherwise you have to filter in your code. In JS it's very easy:
const filtered = {
...data,
search: {
...data.search,
nodes: data.search.nodes.filter(node => node.defaultBranchRef.target.history.totalCount > 0),
}
};

vega-lite scatter plot with hyperlink on each data point is not clicking

I am following this documentation on making href channel inside the encoding of a vega-lite scatter plot.
The data I am using is from an elasticsearch index. This is my code for the plot:
{
$schema: https://vega.github.io/schema/vega-lite/v4.json
data: {
url: {
%context%: true
index: my_index
body: {
size: 10000
}
}
format: {
property: hits.hits
}
}
transform: [
{
calculate: datum._source.price
as: price
}
{
calculate: datum._source.size
as: size
}
{
calculate: "'https://www.example.com/'+datum._source.id"
as: url
}
]
layer: [
{
selection: {
grid: {
type: interval
bind: scales
}
}
mark: {
type: circle
tooltip: true
}
encoding: {
x: {
field: size
type: quantitative
}
y: {
field: price
type: quantitative
}
href: {
field: url
}
}
}
]
}
The code works and on hovering over the scatter points, the mouse changes to a recognised link however the click itself does not work. why is that? the only differences from the documented example is that the data is from elasticsearch and I have a second layer in the plot.
How can I make the hyperlinks work?
To enable the click selection, you need to provide a selection of type: single. Try click the points in the link of editor or try the sample below:
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Using `labelExpr` to show only initial letters of month names.",
"data": {"url": "data/seattle-weather.csv"},
"mark": "circle",
"transform": [
{
"calculate": "'https://www.google.com'",
"as": "url"
}
],
"selection": {"select": {"type": "single"}},
"encoding": {
"href": {"field": "url"},
"x": {
"timeUnit": "month",
"field": "date",
"axis": {"labelAlign": "left", "labelExpr": "datum.label[0]"}
},
"y": {"aggregate": "mean", "field": "precipitation"}
}
}

Amplify GraphQL query filtering is not working as expected

The following two queries should return the same output, but they don't.
I am trying to load links between users on a map, since we have too much payload, I need to split the loading. Therefore I have to use this query to load the links that are necessary.
As mentioned the issue I am having is that these two return different results, which in my opinion they shouldn't. We are using GraphQL with Amplify inside of an React application. The data is stored on AWS.
entry in db:
source: "b864749a-c4bf-4c93-93db-dfa868ffc31d"
target: "cf7f4036-2df2-47ee-a3d7-96b77fc7fd1c"
giving no result:
query ListLinks(
$nextToken: String
) {
listLinks(filter: {
or: [{
and: [{
source: { eq: "b864749a-c4bf-4c93-93db-dfa868ffc31d" },
target: { eq: "cf7f4036-2df2-47ee-a3d7-96b77fc7fd1c" }
}],
and: [{
source: { eq: "cf7f4036-2df2-47ee-a3d7-96b77fc7fd1c" },
target: { eq: "b864749a-c4bf-4c93-93db-dfa868ffc31d" }
}]
}]
}, limit: 999, nextToken: $nextToken) {
items {
id
source
target
relation
verified
talentMap {
id
createdAt
updatedAt
}
createdAt
updatedAt
}
nextToken
}
}
giving result:
query ListLinks(
$nextToken: String
) {
listLinks(filter: {
or: [{
and: [{
target: { eq: "b864749a-c4bf-4c93-93db-dfa868ffc31d" },
source: { eq: "cf7f4036-2df2-47ee-a3d7-96b77fc7fd1c" }
}],
and: [{
target: { eq: "cf7f4036-2df2-47ee-a3d7-96b77fc7fd1c" },
source: { eq: "b864749a-c4bf-4c93-93db-dfa868ffc31d" }
}]
}]
}, limit: 999, nextToken: $nextToken) {
items {
id
source
target
relation
verified
talentMap {
id
createdAt
updatedAt
}
createdAt
updatedAt
}
nextToken
}
}
Any idea why this is the case?

Elasticsearch group by field or missing field

I have a difficulties with elasticsearch.
Here is what I want to do:
Let's say unit of my index looks like this:
{
transacId: "qwerty",
amount: 150,
userId: "adsf",
client: "mobile",
goal: "purchase"
}
I want to build different types of statistics of this data and elasticsearch does it really fast. The problem I have is that in my system user can add new field in transaction on demand. Let's say we have another row in the same index:
{
transacId: "qrerty",
amount: 200,
userId: "adsf",
client: "mobile",
goal: "purchase",
token_1: "game"
}
So now I want to group by token_1.
{
query: {
match: {userId: "asdf"}
},
aggs: {
token_1: {
terms: {field: "token_1"},
aggs: {sumAmt: {sum: {field: "amount"}}}
}
}
}
Problem here that it will aggregate only documents with field token_1. I know there is aggregation missing and I can do something like this:
{
query: {
match: {userId: "asdf"}
},
aggs: {
token_1: {
missing: {field: "token_1"},
aggs: {sumAmt: {sum: {field: "amount"}}}
}
}
}
But in this case it will aggregate only documents without field token_1, what I want is to aggregate both types of documents in on query. I tried do this, but it also didn't work for me:
{
query: {
match: {userId: "asdf"}
},
aggs: {
token_1: {
missing: {field: "token_1"},
aggs: {sumAmt: {sum: {field: "amount"}}}
},
aggs: {
token_1: {
missing: {field: "token_1"},
aggs: {sumAmt: {sum: {field: "amount"}}}
}
}
}
}
I think may be there is something like operator OR in aggregation, but I couldn't find anything. Help me, please.

Resources