MongoDB update and insert on an array - mongodb

I have a mongo document as shown below :
{
"ITEMS": [
{
"BUKRS": "1000",
"GLACC": "476000",
"NETWR": 100
}
],
"EXCEPTIONS": [
{
"CURR": true,
"EVENT": "WEB",
"DATE_TIME": "2020-02-08T22:46:29.219Z"
},
{
"CURR": true,
"EVENT": "WEB",
"DATE_TIME": "2020-02-08T22:46:29.219Z"
},
{
"CURR": false,
"EVENT": "WEB",
"DATE_TIME": "2020-02-08T22:46:29.219Z"
}
]
}
What I need to achieve is in one mongo query, set all EXCEPTIONS.$.CURR:false and insert a new object into EXCEPTIONS array with mostly CURR : true.

You can do it in one DB call using .bulkWrite() for MongoDB version's >= 3.2 :
db.collection.bulkWrite([{
updateOne: {
"filter": {}, // If you've any filters to match a doc give it here
"update": { $set: { "EXCEPTIONS.$[].CURR": false } } // $[] operator updates all elements in an array.
}
}, {
updateOne: {
"filter": {},
"update": {
$push: {
"EXCEPTIONS": {
"CURR": true,
"EVENT": "WEB",
"DATE_TIME": "New_Time"
}
}
}
}
}])
Document in DB :
/* 1 */
{
"_id" : ObjectId("5e475da77f8bc30a7504f0b6"),
"ITEMS" : [
{
"BUKRS" : "1000",
"GLACC" : "476000",
"NETWR" : 100
}
],
"EXCEPTIONS" : [
{
"CURR" : true,
"EVENT" : "WEB",
"DATE_TIME" : "2020-02-08T22:46:29.219Z"
},
{
"CURR" : true,
"EVENT" : "WEB",
"DATE_TIME" : "2020-02-08T22:46:29.219Z"
},
{
"CURR" : false,
"EVENT" : "WEB",
"DATE_TIME" : "2020-02-08T22:46:29.219Z"
}
]
}
Response :
/* 1 */
{
"acknowledged" : true,
"deletedCount" : 0.0,
"insertedCount" : 0.0,
"matchedCount" : 2.0, // It's 2 as it modified array/doc twice
"upsertedCount" : 0.0,
"insertedIds" : {},
"upsertedIds" : {}
}
Result in DB :
/* 1 */
{
"_id" : ObjectId("5e475da77f8bc30a7504f0b6"),
"ITEMS" : [
{
"BUKRS" : "1000",
"GLACC" : "476000",
"NETWR" : 100
}
],
"EXCEPTIONS" : [
{
"CURR" : false,
"EVENT" : "WEB",
"DATE_TIME" : "2020-02-08T22:46:29.219Z"
},
{
"CURR" : false,
"EVENT" : "WEB",
"DATE_TIME" : "2020-02-08T22:46:29.219Z"
},
{
"CURR" : false,
"EVENT" : "WEB",
"DATE_TIME" : "2020-02-08T22:46:29.219Z"
},
{
"CURR" : true,
"EVENT" : "WEB",
"DATE_TIME" : "New_Time"
}
]
}

Related

ElasticSearch filter on array along with multiple match queries

I am trying to filter the documents based on some tags and subcategory.
Some documents:
[{
"_id" : "2oukjh8o9qy2ejhasdkqwe",
"productName" : "ASSORTED DOUGHNUT 1PC",
"productSubCategory" : [
{
"label" : "Veg",
"imageUrl" : "/catImg/fandA.svg"
}
],
"isVisible" : true,
"tags" : [
{
"tagImageUrl" : " ",
"label" : "Favorites",
"tag" : "favorites"
}
]
},
{
"_id" : "638daf9f42e6efc7f06641c2",
"isVisible" : true,
"productName" : "FILTER COFFEE",
"productSubCategory" : [
{
"_id" : ObjectId("638daf18ed445826c06a7328"),
"label" : "Veg"
}
],
"tags" : [
{
"tagImageUrl" : " ",
"label" : "Trending",
"tag" : "trending"
},
{
"tagImageUrl" : " ",
"label" : "Favorites",
"tag" : "favorites"
},
{
"tagImageUrl" : " ",
"label" : "Cabin Friendly",
"tag" : "cabinfriendly"
}
]
},
{
"_id" : "6389d7f942e6efc7f05d51e0",
"isVisible" : true,
"productName" : "ILLY DOPPIO",
"productSubCategory" : [
{
"_id" : ObjectId("638d97236612ca5d5ceb53b9"),
"label" : "Non-Veg"
}
],
"tags" : [
{
"tagImageUrl" : " ",
"label" : "Cabin Friendly",
"tag" : "cabinfriendly"
}
]
}]
Query I am trying
{
"query": {
"bool": {
"must": [
{
"match": {
"productSubCategory.label": {
"query": "Veg",
"operator": "and"
}
}
},
{
"match": {
"isVisible": true
}
}
],
"filter": {
"terms": {
"tags.tag": [
"favorites",
"cabinfriendly"
]
}
}
}
}
}
Requirement
The result documents must have any of the tags.tag provided in the query. Must have isVisible as true and productSubCategory.label as provided in the query.
With the above query I am getting Non-Veg items as well.
Because you are using match query which will do the free text search and it will match with the non-veg as well. You can use term query with keyword type insted of match query like shown below:
{
"query": {
"bool": {
"must": [
{
"term": {
"productSubCategory.label.keyword": {
"value": "Veg"
}
}
},
{
"match": {
"isVisible": true
}
}
],
"filter": {
"terms": {
"tags.tag": [
"favorites",
"cabinfriendly"
]
}
}
}
}
}
Please note that i have replace field name productSubCategory.label with productSubCategory.label.keyword

MongoDB get subdocuments array from multiple documents into own array

I have the following document structure.
{
"_id" : "0026",
"description" : "test",
"name" : "test",
"options" : [
{
"_id" : "002",
"color" : true,
"visible" : true,
"label" : "sample",
},
{
"_id" : "003",
"color" : true,
"visible" : true,
"label" : "sample",
}
],
},
{
"_id" : "0027",
"description" : "test",
"name" : "test",
"options" : [
{
"_id" : "001",
"color" : true,
"visible" : true,
"label" : "sample",
},
{
"_id" : "002",
"color" : true,
"visible" : true,
"label" : "sample",
}
],
},
I am trying to return one array of only the 'options' subdocuments that match an options label regex search.
I think I'm pretty much there but I seem to getting back a separate array of options for each document, how do I return just one array of 'options'?
My current code is:
{
$match: {
options: {
$elemMatch: {
label: { $regex: '^sample', $options: 'i' },
},
},
},
},
{ "$unwind": '$options' },
{
$project: {
_id: 0,
options: 1,
},
},
The structure I would like back is just an array of options:
[
{
"_id" : "001",
"color" : true,
"visible" : true,
"label" : "sample",
},
{
"_id" : "002",
"color" : true,
"visible" : true,
"label" : "sample",
},
{
"_id" : "002",
"color" : true,
"visible" : true,
"label" : "sample",
},
{
"_id" : "003",
"color" : true,
"visible" : true,
"label" : "sample",
}
]
Ta.
Always the way, you post a question then finally get the answer yourself!
Just needed to add:
{ $replaceRoot: { newRoot: '$options' } }
as the last step.
Full answer:
{
$match: {
options: {
$elemMatch: {
label: { $regex: '^sample', $options: 'i' },
},
},
},
},
{ "$unwind": '$options' },
{
$project: {
_id: 0,
options: 1,
},
},
{ $replaceRoot: { newRoot: '$options' } },

Group and Merge array of objects

I am struggling around with the aggregation pipeline feature from MongoDB.
So far the output for one result looks like this:
{
"type": "inbound",
"sender": "postAG",
"receiver": "maxMusterMan",
"datetime": "20191125",
"info": [
{
"q": "A",
"value": "5",
"name": null,
"plz": 1234
},
{
"q": "B",
"value": "AS",
"name": "ABS",
"plz": null
},
{
"q": "A",
"value": "5",
"name": "aa",
"plz": null
},
... more objects
]
}
The final result should look like:
{
"type": "inbound",
"sender": "postAG",
"receiver": "maxMusterMan",
"datetime": "20191125",
"info": [
{
"q": "A",
"value": "0",
"name": "aa",
"plz": 1234
},
{
"q": "B",
"value": "AS",
"name": "ABS"
}
]
}
So in a nutshell, I want to group the values from the array field info by the "q" field and merge the objects (newer one overwrites the old value).
Further I would like to remove all the values with value "" or null;
There are more fields in the real payload, so I would like to avoid to add a $cond for each field of the object.
Some approaches so far from my side:
for the cleanup, use a UDF, but this is not possible in the pipeline.
use map-reduce for the group and merge, not available in the pipeline.
Please consider that the input file is the output from the several pipeline steps.
So I can not just use map-reduce alone, first I need the pipeline too.
My idea was to create two views, first will do the pipeline stuff and second map-reduce, is this a good solution?
Thx
Andreas
I didn't really understand from your explanation if you can or cannot use map-reduce.
However assuming you can't and you have to 'concat' the pipelines there is no 'generic' workaround for multiple fields - you have to create a condition for each in the pipeline.
With that said here is a working pipeline:
db.collection.aggregate(
[
{
"$unwind" : "$info"
},
{
"$group" : {
"_id" : "$info.q",
"type" : {
"$first" : "$type"
},
"sender" : {
"$first" : "$sender"
},
"receiver" : {
"$first" : "$receiver"
},
"datetime" : {
"$first" : "$datetime"
},
"values" : {
"$push" : "$info.value"
},
"names" : {
"$push" : "$info.name"
},
"plz" : {
"$push" : "$info.plz"
}
}
},
{
"$project" : {
"_id" : 1.0,
"type" : 1.0,
"sender" : 1.0,
"receiver" : 1.0,
"datetime" : 1.0,
"values" : {
"$filter" : {
"input" : "$values",
"as" : "curr",
"cond" : {
"$or" : [
{
"$ne" : [
"$$curr",
null
]
},
{
"$ne" : [
"$$curr",
""
]
}
]
}
}
},
"names" : {
"$filter" : {
"input" : "$names",
"as" : "curr",
"cond" : {
"$or" : [
{
"$ne" : [
"$$curr",
null
]
},
{
"$ne" : [
"$$curr",
""
]
}
]
}
}
},
"plz" : {
"$filter" : {
"input" : "$plz",
"as" : "curr",
"cond" : {
"$or" : [
{
"$ne" : [
"$$curr",
null
]
},
{
"$ne" : [
"$$curr",
""
]
}
]
}
}
}
}
},
{
"$project" : {
"sender" : 1.0,
"receiver" : 1.0,
"datetime" : 1.0,
"type" : 1.0,
"_id" : 1.0,
"value" : {
"$cond" : {
"if" : {
"$gt" : [
{
"$size" : "$values"
},
0.0
]
},
"then" : {
"$arrayElemAt" : [
"$values",
-1.0
]
},
"else" : null
}
},
"name" : {
"$cond" : {
"if" : {
"$gt" : [
{
"$size" : "$names"
},
0.0
]
},
"then" : {
"$arrayElemAt" : [
"$names",
-1.0
]
},
"else" : null
}
},
"plz" : {
"$cond" : {
"if" : {
"$gt" : [
{
"$size" : "$plz"
},
0.0
]
},
"then" : {
"$arrayElemAt" : [
"$plz",
-1.0
]
},
"else" : null
}
}
}
},
{
"$addFields" : {
"infoArray" : [
{
"k" : "type",
"v" : "$_id"
},
{
"k" : "value",
"v" : "$value"
},
{
"k" : "name",
"v" : "$name"
},
{
"k" : "plz",
"v" : "$plz"
}
]
}
},
{
"$addFields" : {
"info" : {
"$arrayToObject" : {
"$filter" : {
"input" : "$infoArray",
"as" : "curr",
"cond" : {
"$ne" : [
"$$curr.v",
null
]
}
}
}
}
}
},
{
"$group" : {
"_id" : null,
"type" : {
"$first" : "$type"
},
"sender" : {
"$first" : "$sender"
},
"receiver" : {
"$first" : "$receiver"
},
"datetime" : {
"$first" : "$datetime"
},
"info" : {
"$push" : "$info"
}
}
}
]
)

Elasticsearch iterate over range query result in nested object

I have a elasticsearch index which is having a nested object called availability which has a date and a boolean field , the mapping schema is as follows
{
"hotel_nested" : {
"mappings" : {
"doc" : {
"properties" : {
"amenities" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"availability" : {
"type" : "nested",
"properties" : {
"date" : {
"type" : "date",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
},
"format" : "MM/dd/yyyy HH:mm:ss||MM/dd/yyyy||epoch_millis"
},
"status" : {
"type" : "boolean"
}
}
},
"dailyRate" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"destination" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"hotelName" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"location" : {
"properties" : {
"lat" : {
"type" : "float"
},
"lon" : {
"type" : "float"
}
}
},
"maxOccupancy" : {
"type" : "long"
},
"propertyType" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"roomType" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"starRating" : {
"type" : "float"
}
}
}
}
}
}
Here is one of the object
{
"_index" : "hotel_nested",
"_type" : "doc",
"_id" : "14",
"_score" : 1.0,
"_source" : {
"roomType" : "Executive",
"destination" : "Albuquerque",
"maxOccupancy" : 4,
"starRating" : 6.8,
"hotelName" : "Lotte Hotel Seoul",
"amenities" : [
"Spa",
"Internet",
"Free parking",
"Air conditioning",
"Laundry Service",
"Business Services"
],
"location" : {
"lat" : 56.76755,
"lon" : -110.75792
},
"propertyType" : "Hotel",
"dailyRate" : "$178.96",
"availability" : [
{
"date" : "10/1/2017",
"status" : true
},
{
"date" : "10/2/2017",
"status" : true
},
{
"date" : "10/3/2017",
"status" : true
},
{
"date" : "10/4/2017",
"status" : false
},
{
"date" : "10/5/2017",
"status" : false
},
{
"date" : "10/6/2017",
"status" : false
},
{
"date" : "10/7/2017",
"status" : true
},
{
"date" : "10/8/2017",
"status" : true
},
{
"date" : "10/9/2017",
"status" : false
},
{
"date" : "10/10/2017",
"status" : false
},
{
"date" : "10/11/2017",
"status" : true
},
{
"date" : "10/12/2017",
"status" : false
},
{
"date" : "10/13/2017",
"status" : false
},
{
"date" : "10/14/2017",
"status" : true
},
{
"date" : "10/15/2017",
"status" : true
},
{
"date" : "10/16/2017",
"status" : true
},
{
"date" : "10/17/2017",
"status" : false
},
{
"date" : "10/18/2017",
"status" : true
},
{
"date" : "10/19/2017",
"status" : false
},
{
"date" : "10/20/2017",
"status" : true
},
{
"date" : "10/21/2017",
"status" : false
},
{
"date" : "10/22/2017",
"status" : true
},
{
"date" : "10/23/2017",
"status" : true
},
{
"date" : "10/24/2017",
"status" : true
},
{
"date" : "10/25/2017",
"status" : false
},
{
"date" : "10/26/2017",
"status" : false
},
{
"date" : "10/27/2017",
"status" : false
},
{
"date" : "10/28/2017",
"status" : true
},
{
"date" : "10/29/2017",
"status" : true
},
{
"date" : "10/30/2017",
"status" : true
},
{
"date" : "10/31/2017",
"status" : true
},
{
"date" : "11/1/2017",
"status" : true
},
{
"date" : "11/2/2017",
"status" : false
},
{
"date" : "11/3/2017",
"status" : false
},
{
"date" : "11/4/2017",
"status" : false
},
{
"date" : "11/5/2017",
"status" : false
},
{
"date" : "11/6/2017",
"status" : true
},
{
"date" : "11/7/2017",
"status" : false
},
{
"date" : "11/8/2017",
"status" : false
},
{
"date" : "11/9/2017",
"status" : false
},
{
"date" : "11/10/2017",
"status" : false
},
{
"date" : "11/11/2017",
"status" : false
},
{
"date" : "11/12/2017",
"status" : false
},
{
"date" : "11/13/2017",
"status" : false
},
{
"date" : "11/14/2017",
"status" : true
},
{
"date" : "11/15/2017",
"status" : true
},
{
"date" : "11/16/2017",
"status" : false
},
{
"date" : "11/17/2017",
"status" : true
},
{
"date" : "11/18/2017",
"status" : false
},
{
"date" : "11/19/2017",
"status" : true
},
{
"date" : "11/20/2017",
"status" : true
},
{
"date" : "11/21/2017",
"status" : true
},
{
"date" : "11/22/2017",
"status" : true
},
{
"date" : "11/23/2017",
"status" : false
},
{
"date" : "11/24/2017",
"status" : false
},
{
"date" : "11/25/2017",
"status" : false
},
{
"date" : "11/26/2017",
"status" : true
},
{
"date" : "11/27/2017",
"status" : true
},
{
"date" : "11/28/2017",
"status" : false
},
{
"date" : "11/29/2017",
"status" : false
},
{
"date" : "11/30/2017",
"status" : false
},
{
"date" : "12/1/2017",
"status" : true
},
{
"date" : "12/2/2017",
"status" : true
},
{
"date" : "12/3/2017",
"status" : true
},
{
"date" : "12/4/2017",
"status" : true
},
{
"date" : "12/5/2017",
"status" : true
},
{
"date" : "12/6/2017",
"status" : true
},
{
"date" : "12/7/2017",
"status" : false
},
{
"date" : "12/8/2017",
"status" : false
},
{
"date" : "12/9/2017",
"status" : true
},
{
"date" : "12/10/2017",
"status" : false
},
{
"date" : "12/11/2017",
"status" : true
},
{
"date" : "12/12/2017",
"status" : false
},
{
"date" : "12/13/2017",
"status" : true
},
{
"date" : "12/14/2017",
"status" : true
},
{
"date" : "12/15/2017",
"status" : true
},
{
"date" : "12/16/2017",
"status" : false
},
{
"date" : "12/17/2017",
"status" : true
},
{
"date" : "12/18/2017",
"status" : true
},
{
"date" : "12/19/2017",
"status" : false
},
{
"date" : "12/20/2017",
"status" : true
},
{
"date" : "12/21/2017",
"status" : true
},
{
"date" : "12/22/2017",
"status" : false
},
{
"date" : "12/23/2017",
"status" : false
},
{
"date" : "12/24/2017",
"status" : false
},
{
"date" : "12/25/2017",
"status" : false
},
{
"date" : "12/26/2017",
"status" : false
},
{
"date" : "12/27/2017",
"status" : false
},
{
"date" : "12/28/2017",
"status" : false
},
{
"date" : "12/29/2017",
"status" : false
},
{
"date" : "12/30/2017",
"status" : true
},
{
"date" : "12/31/2017",
"status" : true
}
]
}
}
My issue is that I want to search between two dates and find out if the hotel availability status is true for all dates between the two dates with also matching the city name at the crude level,i have other criteria to search also which i think i can handle,but finding true status for all dates between two dates is bugging me
eg search query parameters city Albuquerque,start date 10/22/2017 and end date 10/24/2017
I have created a query which is giving undesired results, my query is
{
"query": {
"bool": {
"must":[
{
"match": {
"destination": {
"query": "Albuquerque" ,
"operator": "and"
}
}
}
],
"filter": {
"bool": {
"must": [ {
"nested": {
"path": "availability",
"query": {
"bool": {
"must": [
{
"range": {
"availability.date":{ "gte": "10/22/2017",
"lte":"10/24/2017"}
}
},
{
"term": {
"availability.status": "true"
}
}
]
}
}
}
}
]
}
}
}
}
}
The first hit of this query is
{
"_index": "hotel_nested",
"_type": "doc",
"_id": "305",
"_score": 4.815987,
"_source": {
"roomType": "Executive",
"destination": "Albuquerque",
"maxOccupancy": 2,
"starRating": 4.2,
"hotelName": "Sheraton San Diego Hotel & Marina",
"amenities": [
"Kitchen",
"Air conditioning",
"Laundry Service",
"Business Services",
"Free parking",
"Spa"
],
"location": {
"lat": 54.92887,
"lon": -101.31256
},
"propertyType": "Hotel",
"dailyRate": "$462.59",
"availability": [
{
"date": "10/1/2017",
"status": false
},
{
"date": "10/2/2017",
"status": true
},
{
"date": "10/3/2017",
"status": false
},
{
"date": "10/4/2017",
"status": true
},
{
"date": "10/5/2017",
"status": true
},
{
"date": "10/6/2017",
"status": true
},
{
"date": "10/7/2017",
"status": true
},
{
"date": "10/8/2017",
"status": false
},
{
"date": "10/9/2017",
"status": false
},
{
"date": "10/10/2017",
"status": true
},
{
"date": "10/11/2017",
"status": true
},
{
"date": "10/12/2017",
"status": false
},
{
"date": "10/13/2017",
"status": true
},
{
"date": "10/14/2017",
"status": false
},
{
"date": "10/15/2017",
"status": true
},
{
"date": "10/16/2017",
"status": false
},
{
"date": "10/17/2017",
"status": true
},
{
"date": "10/18/2017",
"status": false
},
{
"date": "10/19/2017",
"status": false
},
{
"date": "10/20/2017",
"status": true
},
{
"date": "10/21/2017",
"status": true
},
{
"date": "10/22/2017",
"status": true
},
{
"date": "10/23/2017",
"status": false
},
{
"date": "10/24/2017",
"status": false
},
{
"date": "10/25/2017",
"status": false
},
{
"date": "10/26/2017",
"status": true
},
{
"date": "10/27/2017",
"status": true
},
{
"date": "10/28/2017",
"status": false
},
{
"date": "10/29/2017",
"status": true
},
{
"date": "10/30/2017",
"status": false
},
{
"date": "10/31/2017",
"status": false
},
{
"date": "11/1/2017",
"status": false
},
{
"date": "11/2/2017",
"status": false
},
{
"date": "11/3/2017",
"status": false
},
{
"date": "11/4/2017",
"status": false
},
{
"date": "11/5/2017",
"status": false
},
{
"date": "11/6/2017",
"status": true
},
{
"date": "11/7/2017",
"status": false
},
{
"date": "11/8/2017",
"status": true
},
{
"date": "11/9/2017",
"status": true
},
{
"date": "11/10/2017",
"status": true
},
{
"date": "11/11/2017",
"status": true
},
{
"date": "11/12/2017",
"status": false
},
{
"date": "11/13/2017",
"status": true
},
{
"date": "11/14/2017",
"status": false
},
{
"date": "11/15/2017",
"status": true
},
{
"date": "11/16/2017",
"status": true
},
{
"date": "11/17/2017",
"status": false
},
{
"date": "11/18/2017",
"status": true
},
{
"date": "11/19/2017",
"status": false
},
{
"date": "11/20/2017",
"status": true
},
{
"date": "11/21/2017",
"status": false
},
{
"date": "11/22/2017",
"status": false
},
{
"date": "11/23/2017",
"status": false
},
{
"date": "11/24/2017",
"status": false
},
{
"date": "11/25/2017",
"status": false
},
{
"date": "11/26/2017",
"status": false
},
{
"date": "11/27/2017",
"status": false
},
{
"date": "11/28/2017",
"status": false
},
{
"date": "11/29/2017",
"status": false
},
{
"date": "11/30/2017",
"status": true
},
{
"date": "12/1/2017",
"status": false
},
{
"date": "12/2/2017",
"status": false
},
{
"date": "12/3/2017",
"status": false
},
{
"date": "12/4/2017",
"status": true
},
{
"date": "12/5/2017",
"status": true
},
{
"date": "12/6/2017",
"status": false
},
{
"date": "12/7/2017",
"status": true
},
{
"date": "12/8/2017",
"status": false
},
{
"date": "12/9/2017",
"status": true
},
{
"date": "12/10/2017",
"status": true
},
{
"date": "12/11/2017",
"status": false
},
{
"date": "12/12/2017",
"status": true
},
{
"date": "12/13/2017",
"status": false
},
{
"date": "12/14/2017",
"status": true
},
{
"date": "12/15/2017",
"status": false
},
{
"date": "12/16/2017",
"status": true
},
{
"date": "12/17/2017",
"status": true
},
{
"date": "12/18/2017",
"status": false
},
{
"date": "12/19/2017",
"status": false
},
{
"date": "12/20/2017",
"status": false
},
{
"date": "12/21/2017",
"status": true
},
{
"date": "12/22/2017",
"status": true
},
{
"date": "12/23/2017",
"status": false
},
{
"date": "12/24/2017",
"status": false
},
{
"date": "12/25/2017",
"status": true
},
{
"date": "12/26/2017",
"status": false
},
{
"date": "12/27/2017",
"status": true
},
{
"date": "12/28/2017",
"status": false
},
{
"date": "12/29/2017",
"status": false
},
{
"date": "12/30/2017",
"status": true
},
{
"date": "12/31/2017",
"status": false
}
]
}
}
In this hit status for dates 10/23/2017 and 10/24/2017 is false
Can someone guide me in the correct direction or maybe give a example search query to solve this problem
You need to put your nested query under must clause. Add the inner_hits key at the bottom of the nested query AND enable specific _source fields at the head (because we don't care about the rest of the sub-documents who don't match the nested query) as follows:
{
"_source": [
"hotelName",
"dailyRate"
],
"query": {
"bool": {
"must": [
{
"match": {
"destination": {
"query": "Albuquerque",
"operator": "and"
}
}
},
{
"nested": {
"path": "availability",
"query": {
"bool": {
"must": [
{
"range": {
"availability.date": {
"gte": "10/22/2017",
"lte": "10/24/2017"
}
}
},
{
"term": {
"availability.status": "true"
}
}
]
}
},
"inner_hits": {
"size": 10
}
}
}
]
}
}
}
Pay attention that now you'll get only nested-documents that comply with the conditions, e.g for your example the result would be:
{
"_index": "hotel_nested",
"_type": "doc",
"_id": "305",
"_score": 4.815987,
"_source": {
"hotelName": "Sheraton San Diego Hotel & Marina",
"dailyRate": "$462.59"
},
"inner_hits": {
"availability": {
"hits": {
"total": 1,
"hits": [
{
"date": "10/22/2017",
"status": true
}
]
}
}
}
}
So now, you will have to check whether all the days in the range 22-24 in October are present.
One shortcut way is to mark "inner_hits":{"size":0} and just look at the result and check if the number of inner_hits equals to the number of the days in the range of 22-24 in October:
"inner_hits"."availability"."hits"."total" == 3

Mongodb .aggregate not matching $or?

Whether a user sends or receives a message, he/she should be able to archive the message for him/herself.
This .aggregate $or, however, only returns docs that the user is the recipient of ('to') that he/she has marked 'archive':'true'. It does accurately filter messages according to the 'value' Booleans.
Models.Messages.aggregate([
// Match documents
{ "$match": {
"$or" : [
{
"to": {
"$elemMatch": {
"username": 'userA',
"view.archive": true,
"view.bin": false
}
}
},
{
"from" : {
"$elemMatch" : {
"username" : 'userA',
"view.archive": true,
"view.bin": false
}
}
}
],
"$or": [
{ 'value.1': true },
{ 'value.2': true },
{ 'value.3': true },
{ 'value.4': false }
]
}},
// Unwind to de-normalize
{ "$unwind": "$to" },
{ "$unwind": "$from" },
// Match the array elements
{ "$match": {
"to.username": 'userA',
"to.view.archive": true,
"from.username": 'userA',
"from.view.archive": true
}},
// Group back all the elements of the original document
{ "$group": {
"_id": "$_id",
"from": { "$push": "$from" },
"to": { "$push": "$to" },
"message": { "$first": "$message" },
"updated": { "$first": "$updated" }
}},
// Sort by updated, most recent first (descending)
{"$sort": {"updated": -1}}
], function (err, docs) {
How could this be altered so that all the fields of both of the following messages are aggregated for userA:
{
"_id" : ObjectId("53e83867f316ea7f22fd3b2b"),
"updated" : ISODate("2014-08-11T03:29:06.000Z"),
"message" : "message1",
"value" : [
"1" : true,
"2" : false,
"3" : false,
"4" : false
]
"to" : [
{
"user" : ObjectId("53e835bd76e0d04318d8cc4e"),
"username" : "userA",
"_id" : ObjectId("53e83867f316ea7f22fd3b2c"),
"view" : {
"inbox" : false,
"outbox" : false,
"archive" : true,
"bin" : false
}
}
],
"from" : [
{
"user" : ObjectId("53e8360276e0d04318d8cc55"),
"username" : "userB",
"_id" : ObjectId("53e83867f316ea7f22fd3b2d"),
"view" : {
"inbox" : false,
"outbox" : true,
"archive" : false,
"bin" : false
}
}
],
"__v" : 5
}
{
"_id" : ObjectId("53e83867f316ea7f22fd3b2b"),
"updated" : ISODate("2014-08-11T03:29:06.000Z"),
"message" : "message2",
"value" : [
"1" : false,
"2" : true,
"3" : false,
"4" : false
]
"to" : [
{
"user" : ObjectId("53e8360276e0d04318d8cc55"),
"username" : "userB",
"_id" : ObjectId("53e83867f316ea7f22fd3b2c"),
"view" : {
"inbox" : true,
"outbox" : false,
"archive" : false,
"bin" : false
}
}
],
"from" : [
{
"user" : ObjectId("53e835bd76e0d04318d8cc4e"),
"username" : "userA",
"_id" : ObjectId("53e83867f316ea7f22fd3b2d"),
"view" : {
"inbox" : false,
"outbox" : true,
"archive" : true,
"bin" : false
}
}
],
"__v" : 5
}
You can't have two $or fields at the top level of your first $match object, so you need to wrap those in an $and array like the following if they both need to be satisfied:
{ "$match": {
$and: [{
"$or" : [
{
"to": {
"$elemMatch": {
"username": 'userA',
"view.archive": true,
"view.bin": false
}
}
},
{
"from" : {
"$elemMatch" : {
"username" : 'userA',
"view.archive": true,
"view.bin": false
}
}
}
]}, {
"$or": [
{ 'value.1': true },
{ 'value.2': true },
{ 'value.3': true },
{ 'value.4': false }
]
}
]
}}
There's a lot going on in your pipeline, so this may not be the only problem.