Conditionally group and sum of the elements from an array - java

I want to group by APPName and I want find how many PrestoBarImpression, PrestoKeyCountChange, PrestoTileImpression for every application for a particular day (just the sum of order counts).
This is so I can generate a report with this information. I need how many order counts of PrestoTileImpression, how many order counts of PrestoBarImpression, how many order counts of PrestoTileClick for every application.
The below is my Document.
{
"ClientId": "XYZ123",
"location": {
"Name": "Hyderabad",
"Country": "India",
"Zip": "500084",
"Gps": {
"lat": "17.463607",
"lon": "78.344279"
}
},
"Network": {
"Operator": "Airtel",
"Type": "wifi",
"TowerID": "123",
"IP": "1.1.1.1"
},
"SessionTimeStamp": {
"Start": ISODate("2015-06-02T05:36:49.045 Z"),
"End": ISODate("2015-06-02T05:36:56.045 Z"),
"Duration": "7000"
},
"AppName": "WhatsApp",
"Text": "Key1 Key2 Key3 Key4",
"Actions": [{
"Type": "PrestoBarImpression",
"CampaignId": 1,
"keyword": "key1",
"prestoCount": 1,
"duration": 100,
"OrderCount": 1
}, {
"Type": "PrestoKeyCountChange",
"CampaignId": 1,
"keyword": "key1",
"prestoCount": 1,
"OrderCount": 2
}, {
"Type": "PrestoBarImpression",
"CampaignId": 2,
"keyword": "key2",
"prestoCount": 2,
"duration": 150,
"OrderCount": 3
}, {
"Type": "PrestoKeyCountChange",
"CampaignId": "2",
"keyword": "key2",
"prestoCount": 2,
"OrderCount": 4
}, {
"Type": "PrestoBarImpression",
"CampaignId": 1,
"keyword": "key3",
"prestoCount": 2,
"duration": 200,
"OrderCount": 5
}, {
"Type": "PrestoTileImpression",
"CampaignId": 1,
"duration": 200,
"OrderCount": 6
}, {
"Type": "PrestoTileImpression",
"AdditionalAction": "swipeRight",
"CampaignId": 2,
"duration": 200,
"OrderCount": 7
}, {
"Type": "PrestoTileClick",
"AdditionalAction": "swipeRight",
"CampaignId": 2,
"OrderCount": 8
}, {
"Type": "PrestoBarImpression",
"CampaignId": 2,
"keyword": "key4",
"prestoCount": 2,
"duration": 150,
"OrderCount": 9
}]
}
I got the below output by using #Viswas response I made a query.
Query
[
{
"$match":{
"SessionTimeStamp.Start":{
"$gte": ISODate("2015-06-01T18:30:00.000 Z"),
"$lte": ISODate("2015-06-04T18:29:59.000 Z")
}
}
},
{
"$unwind":"$Actions"
},
{
"$match":{
"Actions.Type":{
"$in":[
"PrestoBarImpression",
"PrestoKeyCountChange",
"PrestoTileImpression"
]
}
}
},
{
"$group":{
"_id":{
"AppName":"$AppName",
"type":"$Actions.Type"
},
"total":{
"$sum":"$Actions.OrderCount"
}
}
},
{
"$sort":{
"total":1,
}
}
]
Output
{
"result":[
{
"_id":{
"AppName":"WhatsApp",
"type":"PrestoKeyCountChange"
},
"total":6
},
{
"_id":{
"AppName":"hike",
"type":"PrestoKeyCountChange"
},
"total":6
},
{
"_id":{
"AppName":"hike",
"type":"PrestoTileImpression"
},
"total":13
},
{
"_id":{
"AppName":"WhatsApp",
"type":"PrestoTileImpression"
},
"total":13
},
{
"_id":{
"AppName":"hike",
"type":"PrestoBarImpression"
},
"total":18
},
{
"_id":{
"AppName":"WhatsApp",
"type":"PrestoBarImpression"
},
"total":18
}
],
"ok":1.0000000000000000
}
I need the output in below format
[
{
"AppName":"WhatsApp",
" PrestoTileImpression":13,
"PrestoKeyCountChange":6,
"PrestoBarImpression":18,
"count":"10 (This is how many times thee Application presents in document, because I need to find top 10 apps Need to sort the output by this count)"
},
{
"AppName":"Hike",
" PrestoTileImpression":13,
"PrestoKeyCountChange":6,
"PrestoBarImpression":18,
"count":"10 "
}
]

It's really all about filtering the array content to get just the items you want in the sum:
db.collection.aggregate([
// Filter documents with matching entries first
{ "$match": {
"Actions.Type": { "$in": [
"PrestoBarImpression",
"PrestoKeyCountChange",
"PrestoTileImpression"
]}
}},
// Unwind the array entries
{ "$unwind": "$Actions" },
// Filter to only keep desired array entries
{ "$match": {
"Actions.Type": { "$in": [
"PrestoBarImpression",
"PrestoKeyCountChange",
"PrestoTileImpression"
]}
}},
// Group by AppName and current day (finishing)
{ "$group": {
"_id": {
"AppName": "$AppName",
"day": {
"year": { "$year": "$SessionTimeStamp.End" },
"month": { "$month": "$SessionTimeStamp.End" },
"day": { "$dayOfMonth": "$SessionTimeStamp.End" }
},
"type": "$Actions.Type"
},
"total": { "$sum": "$Actions.OrderCount" }
}},
// Sort as however you require
{ "$sort": {
"_id.AppName": 1,
"_id.day": 1,
"_id.type": 1,
"total": -1
}}
])
Or if you want all those fields per document then right after the existing group add:
{ "$group": {
"_id": {
"AppName": "$_id.AppName",
"day": "$_id.day",
},
"PrestoBarImpression": { "$sum": {
"$cond": [
{ "$eq": [ "$_id.type", "PrestoBarImpression" ] },
"$total",
0
]
}},
"PrestoKeyCountChange": { "$sum": {
"$cond": [
{ "$eq": [ "$_id.type", "PrestoKeyCountChange" ] },
"$total",
0
]
}},
"PrestoTileImpression": { "$sum": {
"$cond": [
{ "$eq": [ "$_id.type", "PrestoTileImpression" ] },
"$total",
0
]
}}
}}
Which tallies the totals per field into single documents for "AppName" and "day".
You probably want to add a "date range" match to that first $match pipeline rather than add up everything in the collection and just do so between dates as well.

You should use aggregation to get result.
If you want ActionType wise OrderCount for given date (particular) date then you need to first match start to your date and then group data according to Action.Type.
The query will be as following:
db.collection.aggregate({
$match: {
"SessionTimeStamp.Start": ISODate("2015-06-02T05:36:49.045Z")
}
}, {
$group: {
"_id": "AppName",
"Document": {
$push: {
"SessionTimeStamp": "$SessionTimeStamp",
"Actions": "$Actions",
"AppName": "$AppName"
}
}
}
}, {
$unwind: "$Document"
}, {
$unwind: "$Document.Actions"
}, {
$group: {
_id: "$Document.Actions.Type",
"OrderCount": {
$sum: "$Document.Actions.OrderCount"
},
"App": {
$first: "$Document.AppName"
}
}
}, {
$project: {
"_id": 0,
"OrderCount": 1,
"ActionType": "$_id",
"App": 1
}
})
Edit after comment of question author:
Reference to Duplicate Question by author
Please verify spelling of count for appNames as it is different (count, Count) for some appNames
You should use following query-
db.collection.aggregate({
$match: {
"SessionTimeStamp.Start": {
$gte: ISODate("2015-06-02T05:36:49.045Z")
},
"SessionTimeStamp.End": {
$lte: ISODate("2015-06-02T05:36:56.045Z")
}
}
}, {
$unwind: "$Actions"
}, {
$group: {
"_id": {
"AppName": "$AppName",
"Type": "$Actions.Type"
},
"count": {
"$sum": "$Actions.Count"
},
"appCount": {
$sum: 1
}
}
}, {
$project: {
"AppName": "$_id.AppName",
"Type": "$_id.Type",
"count": 1,
"appCount": 1,
"_id": 0
}
})
If you still want to assign dynamic values as keys then you can iterate over the cursor you get like -
db.collection.aggregate({$match:{"SessionTimeStamp.Start":{$gte:ISODate("2015-06-02T05:36:49.045Z")},
"SessionTimeStamp.End":{$lte:ISODate("2015-06-02T05:36:56.045Z")}}},
{$unwind:"$Actions"},{$group:{"_id":{"AppName":"$AppName","Type":"$Actions.Type"},
"count":{"$sum":"$Actions.Count"},"appCount":{$sum:1}}},
{$project:{"AppName":"$_id.AppName","Type":"$_id.Type","count":1,
"appCount":1,"_id":0}}).forEach( function(myDoc){ var feeType = {};
feeType["AppName"] = myDoc.AppName; feeType[myDoc.Type]= myDoc.count;
feeType["appCount"] = myDoc.appCount; printjson (feeType);})

Related

How to reach Value if value is in form of uuid in Postman

The response body is
{
"name": "1",
"widgets": {
"ijklmnop-abcd-1234-91f0-f51f1825b788": {
"id": "ijklmnop-abcd-1234-91f0-f51f1825b788",
"width": 1760,
"content": {
"params": {
"data": [
0
],
"aggregations": [
],
"valueTypes": [
"none"
]
}
}
},
"abcdefgh-5678-90ds-ae27-abae62385a55": {
"id": "abcdefgh-5678-90ds-ae27-abae62385a55",
"width": 1240,
"content": {
"params": {
"data": 1,
"values": [],
"timestamps": []
}
}
}
}
}
Here I want to extract as well as check id and other parameters inside abcdefgh-5678-90ds-ae27-abae62385a55(uuid) in the body?

Average of difference between the dates

A snippet of my elasticsearch data is like below. Status field is nested.
status: [
{
"updated_at": "2020-08-04 17:18:41",
"created_at": "2020-08-04 17:18:39",
"sub_stage": "Stage1"
},
{
"updated_at": "2020-08-04 17:21:15",
"created_at": "2020-08-04 17:18:41",
"sub_stage": "Stage2"
},
{
"updated_at": "2020-08-04 17:21:15",
"created_at": "2020-08-04 17:21:07",
"sub_stage": "Stage3"
}
]
After aggregating based on some field, I have for each bucket some documents and every document will have status field. Now, what I want is to find the average of time difference between stage1 and stage3.
For ex: Suppose for id = 1 bucket consists of 100 documents. Then for each document I have to find the time difference between stage 1 and stage 3. Then, finally take the average of it.
I am able to perform till aggregation but stuck at finding average.
With some effort, I am using below script but have no idea whether it is correct :
Map findEvent(List events, String type) {
return events.find(it -> it.sub_stage == type);
}
return ChronoUnit.DAYS.between(Instant.parse(findEvent(params._source.events, 'Stage1').timestamp), Instant.parse(findEvent(params._source.events, 'Stage3').timestamp););
Is there any way I can perform this in Java with this script or any other script ?
Roughly, Query looks like:
{
"from": 0,
"size": 0,
"query": {
"bool": {
"must": [
{
"nested": {
"query": {
"bool": {
"should": [
{
"match": {
"status.sub_stage": {
"query": "Stage1",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
}
],
"adjust_pure_negative": true,
"minimum_should_match": "1",
"boost": 1.0
}
},
"path": "status",
"ignore_unmapped": false,
"score_mode": "none",
"boost": 1.0
}
}
],
"adjust_pure_negative": true,
"minimum_should_match": "1",
"boost": 1.0
}
},
"aggregations": {
"id": {
"terms": {
"field": "id.keyword",
"size": 1000,
"min_doc_count": 1,
"shard_min_doc_count": 0,
"show_term_doc_count_error": false,
"order": [
{
"_count": "desc"
},
{
"_key": "asc"
}
]
},
"aggregations": {
"avg time": {
"avg": {
"script": {
"source": "Map findStage(List events, String type) { return events.find(it -> it.sub_stage == type); } return ChronoUnit.DAYS.between(Instant.parse(findStage(ctx._source.status, 'Stage1').timestamp), Instant.parse(findStage(ctx._source.status, 'Stage3').timestamp));",
"lang": "painless"
}
}
}
}
}
}
}

Problem with checking values of JSON array using Rest Assured

I'm trying to add some tests with Rest-Assured to my application, but I can't figure out how to assert some nested values. The error message is :
Expected: (a collection containing "json")
Actual: [[json, spring, gulp, path etc...]]
Here is the code :
when().
get("/api/personsByID/{id}/{count}", 262, 2).
then().
statusCode(200).
body("personDependencies.name", hasItems("json"));
And here is the JSON file that is returned by rest controller:
[
{
"id": 346,
"verified": true,
"displayName": "eda656a2c3cb59ae840e40a28ba4ab50bfb9de0185abcb901c6af6dc59d6668f",
"emails": [
{
"email": "16a23f2e5477df0bbcad718c3abc235b2cb8a1b6648d14f58d42a7be13df2b6e"
}
],
"personDependencies": [
{
"name": "json"
},
{
"name": "spring"
},
{
"name": "gulp"
},
{
"name": "path"
},
{
"name": "junit"
},
{
"name": "activemq"
},
{
"name": "hibernate"
},
{
"name": "jstl"
},
{
"name": "phantomjs"
},
{
"name": "activiti"
},
{
"name": "commons"
},
{
"name": "h2"
},
{
"name": "joda"
},
{
"name": "log4j"
},
{
"name": "exec"
},
{
"name": "admin"
},
{
"name": "coveralls"
},
{
"name": "cxf"
},
{
"name": "cglib"
},
{
"name": "camel"
},
{
"name": "sugaronrest"
},
{
"name": "tslint"
},
{
"name": "httpclient"
},
{
"name": "guava"
},
{
"name": "inventory"
},
{
"name": "jackson"
},
{
"name": "gson"
},
{
"name": "event"
},
{
"name": "OTRS"
},
{
"name": "maven"
},
{
"name": "karma"
},
{
"name": "slf4j"
},
{
"name": "postgresql"
},
{
"name": "typescript"
},
{
"name": "jasmine"
},
{
"name": "spa"
},
{
"name": "javax.servlet"
}
],
"countries": [],
"member_of": [],
"projects": [],
"employee_type": [],
"languages": [
{
"language": "reStructuredText",
"sum": 575
},
{
"language": "JSON",
"sum": 21
},
{
"language": "JavaScript",
"sum": 4467
},
{
"language": "Java",
"sum": 7958
},
{
"language": "Python",
"sum": 2
},
{
"language": "XML",
"sum": 477
},
{
"language": "Plain Text",
"sum": 41
}
],
"distance": 0.6028837702084446
}
]
I have no idea how to make proper assertions, any help would be great. Thanks!
If I am reading your question right you need to check if a certain values are present in a list that is returned for a particular ID
The below should work for you
given().when().get().then().body("find {it.id == 346}.personDependencies.name", hasItems("json", "jackson"));
The first problem you don't need to check the presence of an item with hasItems, you should use hasItem
when().
get("/api/personsByID/{id}/{count}", 262, 2).
then().
statusCode(200).
body("personDependencies.name", hasItem("json"));
Then if you need to add more message to the assertion when the test fails you can do such way:
when().
get("/api/personsByID/{id}/{count}", 262, 2).
then().
statusCode(200).
body("personDependencies.name", describedAs("Array not containing the provided item",hasItem("json")));
In your case you can validate such a way:
when().
get("/api/personsByID/{id}/{count}", 262, 2).
then().
statusCode(200).
body("personDependencies[*].name", hasItem("json"));

Mongodb query by Date field using Spring / Java

I have following Mongodb document. Would like to fetch document where participant = 'xxx' and message.lastmodifiedDate > dt and (message.touserid = 'xxx' or message.fromuserid = 'xxx').
{
"_id": {
"$oid": "575161ea02758f067057b8a8"
},
"_class": "com.idearealty.product.shopchat.persistence.model.Discussion",
"participants": "56d314a8e4b04d7f98cfd0c6,56d5d48ee4b0cc330f512a47,56d9d599e4b0cc330f512aaa,57130299e4b08c554c1092c7,56841002eceefce22f455c7f",
"messages": [
{
"_id": {
"$oid": "575161e802758f067057b8a4"
},
"formuserId": "56841002eceefce22f455c7f",
"fromuser": "9674642375",
"touserId": "56d314a8e4b04d7f98cfd0c6",
"touser": "debopam_r",
"message": "User Creating Discussion",
"isMute": false,
"index": 1,
"createDate": {
"$date": "2016-06-03T10:54:32.428Z"
},
"lastModifiedDate": {
"$date": "2016-06-03T10:54:32.428Z"
},
"createdBy": "9674642375",
"lastModifiedBy": "9674642375"
},
{
"_id": {
"$oid": "575161e902758f067057b8a5"
},
"formuserId": "56841002eceefce22f455c7f",
"fromuser": "9674642375",
"touserId": "56d5d48ee4b0cc330f512a47",
"touser": "Raushan",
"message": "User Creating Discussion",
"isMute": false,
"index": 2,
"createDate": {
"$date": "2016-06-03T10:54:33.006Z"
},
"lastModifiedDate": {
"$date": "2016-06-03T10:54:33.006Z"
},
"createdBy": "9674642375",
"lastModifiedBy": "9674642375"
},
{
"_id": {
"$oid": "575161e902758f067057b8a6"
},
"formuserId": "56841002eceefce22f455c7f",
"fromuser": "9674642375",
"touserId": "56d9d599e4b0cc330f512aaa",
"touser": "anirbanshop1",
"message": "User Creating Discussion",
"isMute": false,
"index": 3,
"createDate": {
"$date": "2016-06-03T10:54:33.572Z"
},
"lastModifiedDate": {
"$date": "2016-06-03T10:54:33.572Z"
},
"createdBy": "9674642375",
"lastModifiedBy": "9674642375"
},
{
"_id": {
"$oid": "575161ea02758f067057b8a7"
},
"formuserId": "56841002eceefce22f455c7f",
"fromuser": "9674642375",
"touserId": "57130299e4b08c554c1092c7",
"touser": "dummyshop",
"message": "User Creating Discussion",
"isMute": false,
"index": 4,
"createDate": {
"$date": "2016-06-03T10:54:34.208Z"
},
"lastModifiedDate": {
"$date": "2016-06-03T10:54:34.208Z"
},
"createdBy": "9674642375",
"lastModifiedBy": "9674642375"
}
],
"productId": "56841004eceefce22f455c9b",
"product": {
"_id": {
"$oid": "56841004eceefce22f455c9b"
},
"category": "Services",
"productName": "Driving School",
"imageurl": "service_icon.png",
"createDate": {
"$date": "2015-12-30T17:10:28.644Z"
},
"lastModifiedDate": {
"$date": "2015-12-30T17:10:28.644Z"
},
"createdBy": "UnAuntenticatedUser",
"lastModifiedBy": "UnAuntenticatedUser"
},
"userToRetailer": {
"57130299e4b08c554c1092c7": {
"_id": {
"$oid": "5713029ae4b08c554c1092c8"
},
"shopName": "dummyshop",
"user": {
"$ref": "IdeaRealtyUser",
"$id": {
"$oid": "57130299e4b08c554c1092c7"
}
}
},
"56d314a8e4b04d7f98cfd0c6": {
"_id": {
"$oid": "56d314a9e4b04d7f98cfd0c7"
},
"shopName": "Test Shop",
"user": {
"$ref": "IdeaRealtyUser",
"$id": {
"$oid": "56d314a8e4b04d7f98cfd0c6"
}
}
},
"56d9d599e4b0cc330f512aaa": {
"_id": {
"$oid": "56d9d59ae4b0cc330f512aab"
},
"shopName": "anirbanshop1",
"user": {
"$ref": "IdeaRealtyUser",
"$id": {
"$oid": "56d9d599e4b0cc330f512aaa"
}
}
},
"56d5d48ee4b0cc330f512a47": {
"_id": {
"$oid": "56d5d48fe4b0cc330f512a48"
},
"shopName": "Kolkata Shop1",
"user": {
"$ref": "IdeaRealtyUser",
"$id": {
"$oid": "56d5d48ee4b0cc330f512a47"
}
}
}
},
"messageCount": 4,
"createDate": {
"$date": "2016-06-03T10:54:34.215Z"
},
"lastModifiedDate": {
"$date": "2016-06-03T10:54:34.215Z"
},
"createdBy": "9674642375",
"lastModifiedBy": "9674642375"
}
I am using following java code to fetch the data, which translates to query
{ "aggregate" : "discussion" , "pipeline" : [ { "$match" : { "participants" : { "$regex" : "56d314a8e4b04d7f98cfd0c6"}}} , { "$unwind" : "$messages"} , { "$match" : { "$and" : [ { "messages.lastModifiedDate" : { "$gte" : { "$date" : "2016-02-28T16:06:11.960Z"}}} , { "$or" : [ { "messages.touserId" : "56d314a8e4b04d7f98cfd0c6"} , { "messages.formuserId" : "56d314a8e4b04d7f98cfd0c6"}]}]}} , { "$sort" : { "messages.lastModifiedDate" : -1}} , { "$skip" : 0} , { "$limit" : 10} , { "$group" : { "_id" : { "_id" : "$_id" , "productId" : "$productId"} , "data" : { "$push" : "$messages"}}} , { "$project" : { "productId" : "$_id.productId" , "data" : 1}}]}
But this query doesn't fecth any record. If I change the Date to ISODate it fetches expected result.
db.discussion.aggregate( [{ "$match" : { "participants" : { "$regex" : "56841002eceefce22f455c7f"}}} , { "$unwind" : "$messages"}, { "$match" : { "$and" : [ { "messages.lastModifiedDate" : { "$gte" : ISODate("2016-02-28T16:38:48.632Z")}} , { "$or" : [ { "messages.touserId" : "56841002eceefce22f455c7f"} , { "messages.formuserId" : "56841002eceefce22f455c7f"}]}]}}]);
Could you please let me know what changes is required so that it fetches using ISODate or while inserting the document it uses normal java.util.Date object? I tried with commented code as well but it didn't work.
public List<Discussion> findInbox(String userid,Date lastloginDate,int skip, int limit){
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
Aggregation aggr = newAggregation(
match(Criteria.where("participants").regex(Pattern.compile(userid))),
unwind("messages"),
match(new Criteria().andOperator(Criteria.where("messages.lastModifiedDate").gte(lastloginDate),new Criteria().orOperator(Criteria.where("messages.touserId").is(userid),Criteria.where("messages.formuserId").is(userid)))),
//match(new Criteria().andOperator(Criteria.where("messages.lastModifiedDate").is(new BasicDBObject("$gte","ISODate("+format.format(lastloginDate)+")")),new Criteria().orOperator(Criteria.where("messages.touserId").is(userid),Criteria.where("messages.formuserId").is(userid)))),
sort(Direction.DESC, "messages.lastModifiedDate"),
skip(skip),
limit(limit),
group("_id","productId").push("messages").as("data"),
project("_id","productId","data")
//project("product","participants","messages")
);
AggregationResults<Discussion> results = mongoTemplate.aggregate(aggr, "discussion", Discussion.class);
List<Discussion> discussions = results.getMappedResults();
return discussions;
}
I was using a Date field from another document. Changing it to Calendar solved the problem.
// Calling method
Calendar cal = Calendar.getInstance();
cal.setTime(loginInfo.getCreateDate());
return customDiscussionRepository.findInbox(activeUser.getId(), cal.getTime(), pageNumber > 0?pageSize*(pageNumber-1):0, pageSize);
// Repository (lastloginDate is the method argument passed from calling method).
Criteria.where("messages.lastModifiedDate").gte(lastloginDate)

ElasticSearch Boolean Query Result Mismatch

This is my index mapping
"index":{
"mappings":{
"patient":{
"properties":{
"LastName":{
"type":"string"
},
"accountType":{
"type":"string"
},
"civilStatus":{
"type":"string"
},
"consultations":{
"type":"nested",
"properties":{
"deleted":{
"type":"boolean"
},
"diagnosis":{
"type":"string",
"index":"not_analyzed"
},
"documentDate":{
"type":"date",
"format":"dateOptionalTime"
},
"firstName":{
"type":"string"
},
"lastName":{
"type":"string"
},
"middleName":{
"type":"string"
},
"prescriptions":{
"type":"string"
}
}
},
"firstName":{
"type":"string"
},
"gender":{
"type":"string"
},
"id":{
"type":"string",
"index":"not_analyzed"
},
"lastName":{
"type":"string"
},
"middleName":{
"type":"string"
},
"occupation":{
"type":"string"
},
"owner":{
"type":"string",
"index":"not_analyzed"
},
"patientPin":{
"type":"string"
}
}
}
}
}
}
Here's the only saved data on ElasticSearch
{
"_index":"index",
"_type":"patient",
"_id":"TENANT1100066",
"_score":1.0,
"_source":{
"id":"100066",
"firstName":"Johnny",
"patientPin":"201408000001",
"middleName":"John ",
"consultations":[
{
"id":null,
"prescriptions":[
],
"diagnosis":[
"headache of unknown origin"
],
"documentDate":"2014-08-05T10:10:00.000+08:00",
"deleted":false,
"lastName":"David",
"firstName":"Johnny ",
"middleName":"John "
}
],
"owner":"TENANT1",
"gender":"MALE",
"occupation":"Unspecified",
"accountType":"INDIVIDUAL",
"civilStatus":"SINGLE",
"lastName":"David"
}
}
And here's the sample query I built to check how boolean query works.
{
"nested" : {
"query" : {
"bool" : {
"must" : [ {
"match" : {
"consultations.diagnosis" : {
"query" : "Kawasaki's Disease",
"type" : "phrase"
}
}
}, {
"match" : {
"consultations.diagnosis" : {
"query" : "Alcohol Intoxication",
"type" : "phrase"
}
}
} ],
"must_not" : {
"match" : {
"consultations.deleted" : {
"query" : "true",
"type" : "boolean"
}
}
},
"should" : {
"match" : {
"consultations.diagnosis" : {
"query" : "headache of unknown origin",
"type" : "phrase"
}
}
}
}
},
"path" : "consultations"
}
Apparently, Kawasaki's Disease and Fibriasis does not exist but headache of unknown origin exists but no
results are returned(Which is Johnny John David) what am I missing here? The operation I had in my mind was
(Kawasaki's Disease AND Fibriasis) OR headache of unknown origin.
What I had in mind was if there was no patients with Kawasakis Disease AND Fibriasis search for Patients with "headache of unknown origin". Which clearly we have, but my query is returning 0 results. what Am I missing here
In your query, you require that matching documents have both (Kawasaki's Disease AND Fibriasis) as you added these 2 conditions in the must clause.
Your document only match your should clause, so it doesn't appear in the search results.
To achieve what you want :
(Kawasaki's Disease AND Fibriasis) OR headache of unknown origin
You can embed the two diseases in another bool query and add this query in the should section of the root query, like this :
{
"query": {
"nested": {
"path": "consultations",
"query": {
"bool": {
"should": [
{
"bool": {
"must": [{
"match_phrase": {
"consultations.diagnosis": "Kawasaki's Disease"
}
},
{
"match_phrase": {
"consultations.diagnosis": "Alcohol Intoxication"
}
}
]
}
},
{
"match_phrase": {
"consultations.diagnosis": "headache of unknown origin"
}
}
],
"minimum_number_should_match": 1
}
}
}
}
}
Which outputs the previously indexed patient :
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.3007646,
"hits": [
{
"_index": "test",
"_type": "patient",
"_id": "TENANT1100066",
"_score": 0.3007646,
"_source": {
"id": "100066",
"firstName": "Johnny",
"patientPin": "201408000001",
"middleName": "John ",
"consultations": [
{
"id": null,
"prescriptions": [],
"diagnosis": [
"headache of unknown origin"
],
"documentDate": "2014-08-05T10:10:00.000+08:00",
"deleted": false,
"lastName": "David",
"firstName": "Johnny ",
"middleName": "John "
}
],
"owner": "TENANT1",
"gender": "MALE",
"occupation": "Unspecified",
"accountType": "INDIVIDUAL",
"civilStatus": "SINGLE",
"lastName": "David"
}
}
]
}
}

Categories

Resources