Match multiple items inside a nested array - Elasticsearch - javascript

I've stored documents within my elasticsearch service that are similar to this:
[
{
"first_name": "John",
"last_name": 'Dow',
"statuses": [
{
"name": "STAT1",
"start_date":"2022-10-21T21:03:06",
"happy": false
},
{
"name": "STAT2",
"start_date":"2022-10-21T21:03:06",
"happy": true
},
]
}
...
]
I've a component within my UI where the user can select the required filters that he wants to apply on the data.
For example give me the docs where:
first_name == "John" & last_name== 'Doe'
After the user selecting the desired filters, i'm creating a query similar to this one:
"query": {
"bool": {
"must": [
{
"regexp": {
"first_name": {
"value": ".*John.*"
}
},
"regexp": {
"last_name": {
"value": ".*Doe.*"
}
},
}
],
"should": []
}
}
Now I've a new requirement where i need to allow to filter the documents as follow:
Show me the document where:
statuses.name === STAT1 & statuses.happy === false
and
statuses.name === STAT2 & statuses.happy === true
and
first_name === Jhon
I didn't found any example how to achieve that requirement, any help would be appreciated

You can start with this query. Read more about nested queries.
{
"query": {
"bool": {
"must": [
{
"match": {
"first_name": "john"
}
}
],
"filter": [
{
"nested": {
"path": "statuses",
"query": {
"bool": {
"must": [
{
"match": {
"statuses.name": "STAT1"
}
},
{
"term": {
"statuses.happy": {
"value": "false"
}
}
}
]
}
}
}
},
{
"nested": {
"path": "statuses",
"query": {
"bool": {
"must": [
{
"match": {
"statuses.name": "STAT2"
}
},
{
"term": {
"statuses.happy": {
"value": "true"
}
}
}
]
}
}
}
}
]
}
}
}

Related

Mongodb - watch changestream in documents with nested array element of certain value

Here is my document:
{
"_id": {
"$oid": "6257a55d04bf2167733f5b72"
},
"attributes": {
"CustomerName": "John",
"CustomerID": "28374",
"LoanID": "82349327409234"
"type": "Record",
"Pointers": [
{"type":"car","token_id":"123"},
{"type":"house","token_id":"456"}
]
}
}
Here is my watch query aiming to watch for Pointers elements with type:"car":
var watchCursor = db.loans.watch([
{
$match: {
"$or": [
{
"updateDescription.updatedFields.attributes.Pointers": {
$elemMatch: {
"type": "car"
}
}
},
{
"fullDocument.attributes.Pointers": {
$elemMatch: {
"type": "car"
}
}
}
]
}
}
]);
while (!watchCursor.isExhausted()){
if (watchCursor.hasNext()){
print(JSON.stringify(watchCursor.next()));
}
}
The problem is that I alter the document but it does not return any change results.
As a test, I changed the $elemMatch stage to $exists: true, then alter the document and it returned the changed document successfully.
what's wrong?!

mongodb: How to use variable inside group operator in aggregate operation?

I am tring to make a query where use the value and try to interpolate a string in a new field.
Mongo Database:
[
{
"state": "1",
"events": {
"1": [
{
"date": 123.2,
"msg": "msg1"
},
{
"date": 124.2,
"msg": "msg2"
}
],
"2": [
{
"date": 125.2,
"msg": "msg3"
},
{
"date": 126.2,
"msg": "msg4"
}
],
}
},
{
"state": "2",
"events": {
"1": [
{
"date": 123.2,
"msg": "msg1"
},
{
"date": 124.2,
"msg": "msg2"
}
],
"2": [
{
"date": 125.2,
"msg": "msg3"
},
{
"date": 126.2,
"msg": "msg4"
}
],
}
}
]
Aggregate query:
db.collection.aggregate({
"$match": {
"state": {
"$in": [
"1",
"2"
]
}
}
},
{
"$group": {
"_id": {
"state": "$state"
},
"this_path": {
"$first": {
"$concat": [
"events.",
"$state",
".0.date"
]
}
}
}
})
"this_path" gets "events.1.0.date", but how to use this value, in another query(line), I would like to do like a string interpolation. Some thing like
...
"date": {
"$first": { `\$${this_path}`}
...
so it become the "events.1.date" then "$events.1.0.date" then "123.2"
you can define it by let just for example a fragment from pipeline:
$lookup: {
from: contentCollectionName,
as: 'content',
let: {
parentId: '$id',
},
The id is taken from above matched documents, but it can be anything

Try to query and aggregate in ElasticSearch but aggregrating not working - elasticsearch.js client

I'm trying to query my dataset for two purposes:
Match a term (resellable = true)
Order the results by their price
lowest to highest
Data set/doc is:
"data" : {
"resellable" : true,
"startingPrice" : 0,
"id" : "4emEe_r_x5DRCc5",
"buyNowPrice" : 0.006493, //Changes per object
"sub_title" : "test 1",
"title" : "test 1",
"category" : "Education",
}
//THREE OBJECTS WITH THE VALUES OF 0.006, 0.7, 1.05 FOR BUYNOWPRICE
I have three objects of these with different buyNowPrice
Query with agg is:
{
"query": {
"bool": {
"must": [
{
"term": {
"data.resellable": true
}
}
]
}
},
"from": 0,
"size": 5,
"aggs": {
"lowestPrice": {
"terms": {
"field": "data.buyNowPrice",
"order": {
"lowest_price": "desc"
}
},
"aggs": {
"lowest_price": {
"min": {
"field": "data.buyNowPrice"
}
},
"lowest_price_top_hits": {
"top_hits": {
"size": 5,
"sort": [
{
"data.buyNowPrice": {
"order": "desc"
}
}
]
}
}
}
}
}
}
The query works fine, and the results are 3 objects that have resellable = true
The issue is, the agg is not organizing the results based off the lowest buy now price.
Each result, the order of buyNowPrice is: 1.06, 0.006, 0.7 - which is not ordered properly.
Switching to desc has no affect, so I don't believe the agg is running at all?
EDIT:
Using the suggestion below my query now looks like:
{
"query": {
"bool": {
"must": [
{
"term": {
"data.resellable": true
}
}
]
}
},
"from": 0,
"size": 5,
"aggs": {
"lowestPrice": {
"terms": {
"field": "data.buyNowPrice",
"order": {
"lowest_price": "asc"
}
},
"aggs": {
"lowest_price": {
"min": {
"field": "data.buyNowPrice"
}
},
"lowest_price_top_hits": {
"top_hits": {
"size": 5
}
}
}
}
}
}
With the results of the query being:
total: { value: 3, relation: 'eq' },
max_score: 0.2876821,
hits: [
{
_index: 'education',
_type: 'listing',
_id: '4emEe_r_x5DRCc5', <--- buyNowPrice of 0.006
_score: 0.2876821,
_source: [Object]
},
{
_index: 'education',
_type: 'listing',
_id: '4ee_r_x5DRCc5', <--- buyNowPrice of 1.006
_score: 0.18232156,
_source: [Object]
},
{
_index: 'education',
_type: 'listing',
_id: '4444_r_x5DRCc5', <--- buyNowPrice of 0.7
_score: 0.18232156,
_source: [Object]
}
]
}
EDIT 2:
Removing the query for resellable = true the aggregation will sort properly and return the items in the proper order. But with the query for resellable included, it does not.
I'm assuming this has to do with the _score property overriding the sorting from agg? How would this be fixed
You can use a bucket sort aggregation that is a parent pipeline
aggregation which sorts the buckets of its parent multi-bucket
aggregation. Zero or more sort fields may be specified together with
the corresponding sort order.
Adding a working example (using the same index data as given in the question), search query, and search result
Search Query:
{
"query": {
"bool": {
"must": [
{
"term": {
"data.resellable": true
}
}
]
}
},
"from": 0,
"size": 5,
"aggs": {
"source": {
"terms": {
"field": "data.buyNowPrice"
},
"aggs": {
"latest": {
"top_hits": {
"_source": {
"includes": [
"data.buyNowPrice",
"data.id"
]
}
}
},
"highest_price": {
"max": {
"field": "data.buyNowPrice"
}
},
"bucket_sort_order": {
"bucket_sort": {
"sort": {
"highest_price": {
"order": "desc"
}
}
}
}
}
}
}
}
Search Result:
"buckets": [
{
"key": 1.0499999523162842,
"doc_count": 1,
"highest_price": {
"value": 1.0499999523162842
},
"latest": {
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.08701137,
"hits": [
{
"_index": "stof_64364468",
"_type": "_doc",
"_id": "3",
"_score": 0.08701137,
"_source": {
"data": {
"id": "4emEe_r_x5DRCc5",
"buyNowPrice": 1.05 <-- note this
}
}
}
]
}
}
},
{
"key": 0.699999988079071,
"doc_count": 1,
"highest_price": {
"value": 0.699999988079071
},
"latest": {
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.08701137,
"hits": [
{
"_index": "stof_64364468",
"_type": "_doc",
"_id": "2",
"_score": 0.08701137,
"_source": {
"data": {
"id": "4emEe_r_x5DRCc5",
"buyNowPrice": 0.7 <-- note this
}
}
}
]
}
}
},
{
"key": 0.006000000052154064,
"doc_count": 1,
"highest_price": {
"value": 0.006000000052154064
},
"latest": {
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.08701137,
"hits": [
{
"_index": "stof_64364468",
"_type": "_doc",
"_id": "1",
"_score": 0.08701137,
"_source": {
"data": {
"id": "4emEe_r_x5DRCc5",
"buyNowPrice": 0.006 <-- note this
}
}
}
]
}
}
}
]
Update 1:
If you modify your search query as :
{
"query": {
"bool": {
"must": [
{
"term": {
"data.resellable": true
}
}
]
}
},
"aggs": {
"lowestPrice": {
"terms": {
"field": "data.buyNowPrice",
"order": {
"lowest_price": "asc" <-- change the order here
}
},
"aggs": {
"lowest_price": {
"min": {
"field": "data.buyNowPrice"
}
},
"lowest_price_top_hits": {
"top_hits": {
"size": 5
}
}
}
}
}
}
Running the above search query also, you will get your required results.

Adding property to mulitple documents in mongoDB

I have this data structure:
{
"_id": "5ebd08794bcc8d2fd893f4a7",
"username": "johan#gmail.com",
"password": "123",
"decks": [{
"cards": [{
"_id": "5ebd08794bcc8d2fd893f4a9",
"planeetnaam": "Venus",
"kleur": "Grijs"
},
{
"_id": "5ebd08794bcc8d2fd893f4aa",
"planeetnaam": "Neptunus",
"kleur": "Paars"
}
],
"_id": "5ebd08794bcc8d2fd893f4a8",
"name": "Planeten"
},
{
"cards": [{
"_id": "5ebd08794bcc8d2fd893f4ac",
"diernaam": "Hond",
"poten": "4"
},
{
"_id": "5ebd08794bcc8d2fd893f4ad",
"diernaam": "Kangoeroe",
"poten": "2"
}
],
"_id": "5ebd08794bcc8d2fd893f4ab",
"name": "Dieren"
}
],
"__v": 0
}
Now i want to add a new property to all the cards in deck with deckname: "Planeten". How do i do this with a mongoose query?
The cards array of deck "Planeten" should look like this after the query
"cards": [{
"_id": "5ebd08794bcc8d2fd893f4a9",
"planeetnaam": "Venus",
"kleur": "Grijs",
"newProp": null
},
{
"_id": "5ebd08794bcc8d2fd893f4aa",
"planeetnaam": "Neptunus",
"kleur": "Paars",
"newProp": null
}
],
EDIT:
This works in Robo3T:
db.getCollection('users').findOneAndUpdate(
{ '_id': ObjectId("5eba9ee0abfaf237f81fb104") },
{ $set: { 'decks.$[deck].cards.$[].newProp': null } },
{ arrayFilters: [{ 'deck._id': ObjectId("5eba9ee0abfaf237f81fb108") } ] }
)
But the server query doesnt edit any data:
User.findOneAndUpdate(
{ '_id': req.session.userid },
{ $set: { 'decks.$[deck].cards.$[].newProp': null } },
{ arrayFilters: [{ 'deck._id': req.params.deckid } ] }, function(err, user){
res.send('test');
})
Thanks in advance
you can use array update operators
the query may look something like that
db.collection.updateOne(
{ _id: <ObjectId> }, // the filter part
{ $set: { 'decks.$[deck].cards.$[].newProp': null } },
{ arrayFilters: [{ 'deck.name': 'Planeten' }] }
)
$[deck] refers to each element in the decks array
$[] is used to update all the elements in the cards array
your function may look something like that
User.updateOne(
{ '_id': req.session.userid },
{ $set: { 'decks.$[deck].cards.$[].newProp': null } },
{ arrayFilters: [{ 'deck.name': 'Planeten' }] })
.then(function (user) {
if (!user) {
res.status(404).send('Er ging helaas iets fout')
} else {
res.status(201).send("Card is toegevoegd");
}
})
hope it helps

How to print json object property values?

I have a json object like this:
JsonQuery = ​'{
"from": 0,
"size": 200,
"sort": [{
"Modified": {
"order": "desc"
}
}],
"query": {
"bool": {
"must": [{
"term": {
"CollectionId": {
"value": "abcd"
}
}
}, {
"terms": {
"Container": ["en-us"]
}
}],
"must_not": [{
"wildcard": {
"_type": {
"value": "##"
}
}
}, {
"bool": {
"filter": {
"exists": {
"field": "DynamicProperties.MainSpec"
}
},
"filter": {
"exists": {
"field": "DynamicProperties.ExtendedSpec"
}
}
}
}]
}
}
}';
I am creating a javascript object by doing
var obj = JSON.parse(JsonQuery);
I go in chrome console and I write obj and hit enter and it displays the object properly but when I try to access the property of the object, it keeps saying undefined.
For example: I am using obj.size.
You only have a gremlin on your first line (JsonQuery = '), try to remove it and retry.
jsonQuery = '{"from":0,"size":200,"sort":[{"Modified":{"order":"desc"}}],"query":{"bool":{"must":[{"term":{"CollectionId":{"value":"abcd"}}},{"terms":{"Container":["en-us"]}}],"must_not":[{"wildcard":{"_type":{"value":"##"}}},{"bool":{"filter":{"exists":{"field":"DynamicProperties.MainSpec"}},"filter":{"exists":{"field":"DynamicProperties.ExtendedSpec"}}}}]}}}';
var obj = JSON.parse(jsonQuery);
console.log(obj.size);

Categories