elasticsearch "more like this" in elastic4s boolean query - scala

I am using elastic4s 1.5.10 and trying to build up a query that I prepared on elasticsarch REST endpoint. Now trying to rewrite to elastic4s dsl.
POST /index_name/type/_search
{
"_source":{"include":["name","surname"]},
"query": {
"bool": {
"must": [
{
"more_like_this": {
"fields": ["desc"],
"ids": ["472825948"],
"min_term_freq":0,
"max_query_terms":200
}
},
{
"match": {"city": "London"}
},
{
"match": {"operation": "add"}
}
]
}
}
}
The goal of this query is get similar items to 472825948 which has the same operation (add) in the same city (London).
My attempt in elastic4s follows:
es_client.execute{
search in s"$storage_folder/${typ.name()}" query bool(
must(
morelike id adId in s"$storage_folder/${typ.name()}" fields("desc") minTermFreq(0) maxQueryTerms(200),
matchQuery(field="city",value = "London"),
matchQuery(field="operation",value = "add"))
)sourceInclude("name","surname")
}
}
"morelike" doesn't work in this context. Either the query as it is in raw json doesn't make sense or elastic4s doesn't support this or ...
Could someone help?
Thx

Just for completeness adding response I got here as well.
morelikee is for a request type, morelikeThisQuery is the correct form of the query. So the resulted query should look like as follows
es_client.execute{
search in s"$storage_folder/${typ.name()}" query bool(
must(
morelikeThisQuery fields("desc") ids(adId) minTermFreq(0) maxQueryTerms(200),
matchQuery(field="city",value = "London"),
matchQuery(field="operation",value = "add"))
)sourceInclude("name","surname")
}
}

Related

How to perform addition in already existing json object in mongoDB?

I want to add the cost of a particular month for a specific category. This is my object stored in MongoDB :
{
"2022":{
"January":{
"Food":30,
"Traveling":0,
"Medical":0,
},
"Feburary":{
"Food":1000,
"Traveling":0,
"Medical":50,
},
"March":{
"Food":100,
"Traveling":20,
"Medical":10,
}
}
}
Now, I am making a patch request:
{
"month":"March",
"monthData":[70,45,100]
}
Now, I want my data to be updated like this:
{
"2022":{
"January":{
"Food":30,
"Traveling":0,
"Medical":0,
},
"Feburary":{
"Food":1000,
"Traveling":0,
"Medical":50,
},
"March":{
"Food":170,
"Traveling":65,
"Medical":110,
}
}
}
What query should I write using Model.findAndUpate(filter,object) so that above thing works.
Your patch request looks to me like this:
db.collection.update({},
{
"$inc": {
"2022.March.Food": 70,
"2022.March.Traveling": 45,
"2022.March.Medical": 100
}
})
Playgroud

How can I return the element I'm looking for inside a nested array?

I have a database like this:
[
{
"universe":"comics",
"saga":[
{
"name":"x-men",
"characters":[
{
"character":"wolverine",
"picture":"618035022351.png"
},
{
"character":"cyclops",
"picture":"618035022352.png"
}
]
}
]
},
{
"universe":"dc",
"saga":[
{
"name":"spiderman",
"characters":[
{
"character":"venom",
"picture":"618035022353.png"
}
]
}
]
}
]
and with this code I manage to update one of the objects in my array. specifically the object where character: wolverine
db.mydb.findOneAndUpdate({
"universe": "comics",
"saga.name": "x-men",
"saga.characters.character": "wolverine"
}, {
$set: {
"saga.$[].characters.$[].character": "lobezno",
"saga.$[].characters.$[].picture": "618035022354.png",
}
}, {
new: false
}
)
it returns all my document, I need ONLY the document matched
I would like to return the object that I have updated without having to make more queries to the database.
Note
I have been told that my code does not work well as it should, apparently my query to update this bad, I would like to know how to fix it and get the object that matches these search criteria.
In other words how can I get this output:
{
"character":"wolverine",
"picture":"618035022351.png"
}
in a single query using filters
{
"universe": "comics",
"saga.name": "x-men",
"saga.characters.character": "wolverine"
}
My MongoDB knowledge prevents me from correcting this.
Use the shell method findAndModify to suit your needs.
But you cannot use the positional character $ more than once while projecting in MongoDb, so you may have to keep track of it yourself at client-side.
Use arrayFilters to update deeply nested sub-document, instead of positional all operator $[].
Below is a working query -
var query = {
universe: 'comics'
};
var update = {
$set: {
'saga.$[outer].characters.$[inner].character': 'lobezno',
'saga.$[outer].characters.$[inner].picture': '618035022354.png',
}
};
var fields = {
'saga.characters': 1
};
var updateFilter = {
arrayFilters: [
{
'outer.name': 'x-men'
},
{
'inner.character': 'wolverine'
}
]
};
db.collection.findAndModify({
query,
update,
fields,
arrayFilters: updateFilter.arrayFilters
new: true
});
If I understand your question correctly, your updating is working as expected and your issue is that it returns the whole document and you don't want to query the database to just to return these two fields.
Why don't you just extract the fields from the document returned from your update? You are not going to the database when doing that.
var extractElementFromResult = null;
if(result != null) {
extractElementFromResult = result.saga
.filter(item => item.name == "x-men")[0]
.characters
.filter(item => item.character == "wolverine")[0];
}

"variable invitationId of type Int! is used in position expecting Int_comparison_exp"

I was trying following query on hasura platform and it gave below error.
I got solution for the same. That's why I'm sharing.
variables:
{
"invaId": 791
}
Query:
mutation UpdateQuery($status:String!,$invaId:Int!) {
update_inva(_set: {status: $status},where:{id:$invaId}){
affected_rows
}
}
Output:
{
"errors": [
{
"extensions": {
"path": "$.selectionSet.update_inva.args.where.id",
"code": "validation-failed"
},
"message": "variable invaId of type Int! is used in position expecting Int_comparison_exp"
}
]
}
I faced this error after passing the variable of type Int!.
The problem is in query.
Look at the where clause
where:{id:$invitationId})
where clause expects the comparison type too for eg. _eq.
That was the exact thing which I was missing.
So, I updated the query as below, and things were running perfectly
Query:
mutation UpdateQuery($status:String!,$invaId:Int!) {
update_inva(_set: {status: $status},where:{id:{_eq:$invaId}}){
affected_rows
}
}

Sails Waterline "Or" clause not working

I tried a lot of time to figure out getting an OR clause working in sails without success.
I am using Sails-MySql adapter.
Have anyone of you done anything like this already? I would appreciate some help.
Basically this is what I want to do:
Do an OR clause on a set of fields along with an AND on another set of fields.
Something like this:
FdbDevice
.find()
.where(or:
[
{ deviceCategory: “cardiology valve bioprosthesis” },
{ deviceCategory: “nephrology haemodialysis catheter” }
]
})
.where(
{ catalogNumber : “Z286004” },
{ modelNumber: “Z286004” }
)
.exec
In this particular case, here is how I would do it:
// Each element in the array is treated as 'or'
var possibleDeviceCategories = [
'cardiology valve bioprosthesis',
'nephrology haemodialysis catheter'
];
FdbDevice
.find({
deviceCategory: possibleDeviceCategories,
catalogNumber: 'Z286004',
modelNumber: 'Z286004'
})
.exec(cb);
Check out the docs for more informations about the Waterline's query language.
you can try something like that, into the find:
FdbDevice
.find({or:
[
{ deviceCategory: “cardiology valve bioprosthesis” },
{ deviceCategory: “nephrology haemodialysis catheter” }
]
})
.where(
{ catalogNumber : “Z286004” },
{ modelNumber: “Z286004” }
)

How to write query to my Cloudant database?

I am trying to achieve the right query for my NoSQL database, but I am confused how to do it in Cloudant. In SQL with be
SELECT * FROM mydb
WHERE user_permit_doc_id = 10
AND user_tracking_id = 1
My query is like:
https://293e2cb7-3561-4004-a1c3-58d54f517ee6-bluemix.cloudant.com/user_files/_design/user_tracking/_view/new-view?startkey=["user_permit_doc_id:10"]
and it returns all of the docs, not just the ones with this id.
this is m Map Reduce function for the View
function(doc) {
if(doc.user_tracking_id !== null){
emit(doc);
}
}
Example of a doc inside my database of docs
{
"_id": "6e57baa78c6415beeee788bc786cc53a",
"_rev": "5-f15352bce99c307bd246bda4dc0da75a",
"user_tracking_id": "1",
"user_permit_id": "2",
"user_permit_doc_id": "10",
"user_id": "1",
"_attachments": {
"6y41j4i68cic.jpg": {
"content_type": "image/jpeg",
"revpos": 2,
"digest": "md5-KC+G5tbz2UWZSzlPHvBy/Q==",
"length": 68367,
"stub": true
}
}
}
you can change your view into
function(doc) {
if(doc.user_tracking_id !== null){
emit([user_tracking_id, user_permit_doc_id]);
}
}
and then query using the complex key [1, 10]
You would have to incorporate the WHERE user_permit_doc_id = 10 into your map reduce function if you wanted to return only that particular document, like this:
function(doc) {
if(doc.user_permit_doc_id === 10 && doc.user_tracking_id === 1){
emit(doc);
}
}
However, since you are coming over from SQL, you might be more comfortable with Mongo-like queries. If that style of querying your DB suits you better, check out the Cloudant Mango API layer. This API introduces SQL-like querying to NoSQL, actually creating a map reduce function behind the scenes.