I have to manage a wall with comments, each wall have many parent comments and each parent comment have child comments.
my collection walls is like this
groupId : {type: Schema.Types.ObjectId, ref: 'groups', unique: true},
comments : [{
commentId : {type: Schema.Types.ObjectId, ref: 'comments'},
user : {type: Schema.Types.ObjectId, ref: 'users'},
}],
and the collection comments is like this
text : String,
parentCommentId : {type: Schema.Types.ObjectId, ref: 'comments', default : null},
I want to display my wall by parent comments, each child comment under its parent comment.
i tried this query but it didn't return any results
db.getCollection('walls').aggregate([
{$match: {groupId: ObjectId("5e8c5caa75b1cd342a1175eb")}},
{
"$lookup": {
from: "comments",
let: { item: "$comments.commentId" },
pipeline: [
{ $match:
{ $expr: { $eq: [ "$parentCommentId", "$$item" ] }
}
},
{ $project: {
"_id": 1,
"parentCommentId": 1,
"text": 1
} }
],
as: "comments"
}
},
{
$project: {
groupId: 1,
"comments":1,
date: 1
}
}
])
data in walls
{
"_id" : ObjectId("5e95b4b49d3e303d667a8b71"),
"groupId" : ObjectId("5e8c5caa75b1cd342a1175eb"),
"comments" : [
{
"_id" : ObjectId("5e95b4b49d3e303d667a8b72"),
"commentId" : ObjectId("5e95b4b49d3e303d667a8b70")
},
{
"_id" : ObjectId("5e95b4ef80ae1244693aa857"),
"commentId" : ObjectId("5e95b4ef80ae1244693aa856")
},
{
"_id" : ObjectId("5e95b51080ae1244693aa859"),
"commentId" : ObjectId("5e95b51080ae1244693aa858")
},
{
"_id" : ObjectId("5e95b51d80ae1244693aa85b"),
"commentId" : ObjectId("5e95b51d80ae1244693aa85a")
},
{
"_id" : ObjectId("5e95b53580ae1244693aa85e"),
"commentId" : ObjectId("5e95b53580ae1244693aa85c")
}
],
}
data in comments
{
"_id" : ObjectId("5e95b4b49d3e303d667a8b70"),
"parentCommentId" : null,
"text" : "Hello parent 1"
}
{
"_id" : ObjectId("5e95b4ef80ae1244693aa856"),
"parentCommentId" : null,
"text" : "Hello parent 2",
"date" : ISODate("2020-04-14T13:04:47.860Z")
}
{
"_id" : ObjectId("5e95b51080ae1244693aa858"),
"parentCommentId" : ObjectId("5e95b4b49d3e303d667a8b70"),
"text" : "Hello child 1 parent 1"
}
{
"_id" : ObjectId("5e95b51d80ae1244693aa85a"),
"parentCommentId" : ObjectId("5e95b4b49d3e303d667a8b70"),
"text" : "Hello child 2 parent 1"
}
{
"_id": "5e95b53580ae1244693aa85c",
"parentCommentId": "5e95b4ef80ae1244693aa856",
"text": "Hello child 1 parent 2",
}
desired result
{
"success": true,
"data": [
{
"_id": "5e95b4b49d3e303d667a8b71",
"groupId": "5e8c5caa75b1cd342a1175eb",
"comments": [
{
"_id": "5e95b4b49d3e303d667a8b70",
"parentCommentId": null,
"text": "Hello parent 1",
"childs": {
{
"_id": "5e95b51080ae1244693aa858",
"parentCommentId": "5e95b4b49d3e303d667a8b70",
"text": "Hello child 1 parent 1",
},
{
"_id": "5e95b51d80ae1244693aa85a",
"parentCommentId": "5e95b4b49d3e303d667a8b70",
"text": "Hello child 2 parent 1",
},
}
},
{
"_id": "5e95b4ef80ae1244693aa856",
"parentCommentId": null,
"text": "Hello parent 2",
"childs": {
{
"_id": "5e95b53580ae1244693aa85c",
"parentCommentId": "5e95b4ef80ae1244693aa856",
"text": "Hello child 1 parent 2",
}
}
},
],
}
]
}
How can i modify my query ? thank you.
You can use below aggregation
db.walls.aggregate([
{ "$lookup": {
"from": "comments",
"let": { "commentIds": "$comments.commentId" },
"pipeline": [
{ "$match": {
"$expr": { "$in": ["$_id", "$$commentIds"] },
"parentCommentId": null
}},
{ "$sort": { "text": -1 }},
{ "$graphLookup": {
"from": "comments",
"startWith": "$_id",
"connectFromField": "parentCommentId",
"connectToField": "parentCommentId",
"as": "childs"
}}
],
"as": "comments"
}}
])
MongoPlayground
Related
I am new to MongoDB, I have two collections like this :
1st collection name is a
db.a.find()
{
"_id": "1234",
"versions": [{
"owner_id": ObjectId("100000"),
"versions": 1,
"type" : "info",
"items" : ["item1","item3","item7"]
},
{
"owner_id": ObjectId("100001"),
"versions": 2,
"type" : "bug",
"OS": "Ubuntu",
"Dependencies" : "Trim",
"items" : ["item1","item7"]
}
]}
2nd Collection name is b
db.b.find()
{
"_id": ObjectId("100000"),
"email": "abc#xyz.com"
} {
"_id": ObjectId("100001"),
"email": "bbc#xyz.com"
}
Expected output is:
{
"_id": "1234",
"versions":[{
"owner_id": "abc#xyz.com",
"versions": 1,
"type" : "info",
"items" : ["item1","item3","item7"]
},
{
"owner_id": "bbc#xyz.com",
"versions": 2,
"type" : "bug",
"OS": "Ubuntu",
"Dependencies" : "Trim",
"items" : ["item1","item7"]
}
] }
Requirement: fields inside each document of versions are not fixed,
Example : versions[0] have 4 key-value pair and versions[1] have 6 key-value pair.
so I am looking a query which can replace owner_id with email keeping all other filed in output.
I tried :
db.a.aggregate(
[
{$unwind:"$versions"},
{$lookup : {from : "b", "localField":"versions.owner_id", "foreignField":"_id", as :"out"}},
{$project : {"_id":1, "versions.owner_id":{$arrayElemAt:["$out.email",0]}}},
{$group:{_id:"$_id", versions : {$push : "$versions"}}}
]
).pretty()
Please help.
Thank You!!!
Instead of $project pipeline stage use $addFields.
Example:
db.a.aggregate([
{ $unwind: "$versions" },
{
$lookup: {
from: "b",
localField: "versions.owner_id",
foreignField: "_id",
as: "out"
}
},
{
$addFields: {
"versions.owner_id": { $arrayElemAt: ["$out.email",0] }
}
},
{ $group: { _id: "$_id", versions: { $push: "$versions" } } }
]).pretty()
I'd like to find the correct query to return all Boards within the Boards collection where the member id matches 1. Any takers?
My schema as follows:
Within the 'Boards' collection,
{ name: 'Board One',
teams: [
{ name: 'Team One',
members: [
{ id: '1', name: 'Garrett' },
{ id: '2', name: 'Sarah' }
]
},
{ name: 'Team Two',
members: [
{ id: '1', name: 'Garrett' },
{ id: '2', name: 'Jeff' }
]
}
]
},`{ name: 'Board Two',
teams: [
{ name: 'Team One',
members: [
{ id: '1', name: 'Garrett' },
{ id: '2', name: 'Sarah' }
]
},
{ name: 'Team Three',
members: [
{ id: '1', name: 'Jim' },
{ id: '2', name: 'Samson' }
]
}
]
I'm trying to query a object within an array, within array of objects, within a collection. I've tried many variations on the following query..
Boards.find({
'teams': {
$elemMatch: {
'members' : {
$elemMatch :
{
'id' : Meteor.userId()
}
}
}
}
})
I'd like to find the correct query to return all Boards within the Boards collection where the member id matches 1.
Could this be because you are storing id as string in the collection? As you will see below I tried your query replacing Meteor.userId() with a hardcoded string value (with single or double quotes) like '1' or '3' and I believe the query output is what you are looking for.
> db.boards.find().pretty()
{
"_id" : ObjectId("567443e7fba7a186bcd48bfd"),
"name" : "Board One",
"teams" : [
{
"name" : "Team One",
"members" : [
{
"id" : "1",
"name" : "Garrett"
},
{
"id" : "2",
"name" : "Sarah"
}
]
},
{
"name" : "Team Two",
"members" : [
{
"id" : "1",
"name" : "Garrett"
},
{
"id" : "2",
"name" : "Jeff"
}
]
}
]
}
{
"_id" : ObjectId("5674441ffba7a186bcd48bfe"),
"name" : "Board Two",
"teams" : [
{
"name" : "Team One",
"members" : [
{
"id" : "1",
"name" : "Garrett"
},
{
"id" : "2",
"name" : "Sarah"
}
]
},
{
"name" : "Team Three",
"members" : [
{
"id" : "1",
"name" : "Jim"
},
{
"id" : "2",
"name" : "Samson"
}
]
}
]
}
>
> db.boards.find({
... 'teams': {
... $elemMatch: {
... 'members' : {
... $elemMatch :
... {
... 'id' : '1'
... }
... }
... }
... }
... })
{ "_id" : ObjectId("567443e7fba7a186bcd48bfd"), "name" : "Board One", "teams" : [ { "name" : "Team One", "members" : [ { "id" : "1", "name" : "Garrett" }, { "id" : "2", "name" : "Sarah" } ] }, { "name" : "Team Two", "members" : [ { "id" : "1", "name" : "Garrett" }, { "id" : "2", "name" : "Jeff" } ] } ] }
{ "_id" : ObjectId("5674441ffba7a186bcd48bfe"), "name" : "Board Two", "teams" : [ { "name" : "Team One", "members" : [ { "id" : "1", "name" : "Garrett" }, { "id" : "2", "name" : "Sarah" } ] }, { "name" : "Team Three", "members" : [ { "id" : "1", "name" : "Jim" }, { "id" : "2", "name" : "Samson" } ] } ] }
>
>
> db.boards.find({
... 'teams': {
... $elemMatch: {
... 'members' : {
... $elemMatch :
... {
... 'id' : '3'
... }
... }
... }
... }
... })
>
>
I receive a large amount of JSON back (flight data) which I've been thinking about using mongo as the tool to query/filter it before returning back to the UI.
Here's the json response from Sabre (flight search)
{
"OTA_AirLowFareSearchRS": {
"PricedItineraries": {
"PricedItinerary": [
{
"SequenceNumber": 1,
"AirItinerary": {
"OriginDestinationOptions": {
"OriginDestinationOption": [
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-12T11:40:00",
"ArrivalDateTime": "2015-11-12T17:35:00",
"FlightNumber": "1980"
},
{
"DepartureDateTime": "2015-11-12T19:35:00",
"ArrivalDateTime": "2015-11-13T02:00:00",
"FlightNumber": "760"
}
]
},
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-19T08:25:00",
"ArrivalDateTime": "2015-11-19T11:40:00",
"FlightNumber": "763"
},
{
"DepartureDateTime": "2015-11-19T12:55:00",
"ArrivalDateTime": "2015-11-19T15:05:00",
"FlightNumber": "1985"
}
]
}
]
}
},
"AirItineraryPricingInfo": [
{
"ItinTotalFare": {
"TotalFare": {
"Amount": 269.56,
"CurrencyCode": "GBP"
}
}
}
]
},
{
"SequenceNumber": 2,
"AirItinerary": {
"OriginDestinationOptions": {
"OriginDestinationOption": [
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-12T16:45:00",
"ArrivalDateTime": "2015-11-12T22:40:00",
"FlightNumber": "1986"
},
{
"DepartureDateTime": "2015-11-13T00:40:00",
"ArrivalDateTime": "2015-11-13T07:10:00",
"FlightNumber": "762"
}
]
},
{
"ElapsedTime": 640,
"FlightSegment": [
{
"DepartureDateTime": "2015-11-19T08:25:00",
"ArrivalDateTime": "2015-11-19T11:40:00",
"FlightNumber": "763"
},
{
"DepartureDateTime": "2015-11-19T12:55:00",
"ArrivalDateTime": "2015-11-19T15:05:00",
"FlightNumber": "1985"
}
]
}
]
}
},
"AirItineraryPricingInfo": [
{
"ItinTotalFare": {
"TotalFare": {
"Amount": 269.56,
"CurrencyCode": "GBP"
}
}
}
]
},
{
"SequenceNumber": 6,
"AirItinerary": {
"OriginDestinationOptions": {
"OriginDestinationOption": [
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-12T11:40:00",
"ArrivalDateTime": "2015-11-12T17:35:00",
"FlightNumber": "1980"
},
{
"DepartureDateTime": "2015-11-12T19:35:00",
"ArrivalDateTime": "2015-11-13T02:00:00",
"FlightNumber": "760"
}
]
},
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-19T03:15:00",
"ArrivalDateTime": "2015-11-19T06:30:00",
"FlightNumber": "761"
},
{
"DepartureDateTime": "2015-11-19T12:55:00",
"ArrivalDateTime": "2015-11-19T15:05:00",
"FlightNumber": "1985"
}
]
}
]
}
},
"AirItineraryPricingInfo": [
{
"ItinTotalFare": {
"TotalFare": {
"Amount": 269.56
}
}
}
]
}
]
}
}
}
I've been trying to get this into a view that I want but struggling with the complexity of all the nested arrays. My question is how can I achieve a desired result like this:
{
'Price': 269.56, <-- //Group on price (TotalFare)
'Outbound': [{
<Outbound Flights> <--- //$push? flights at array position [0] of OriginDestinationOption
}],
'Inbound': [{
<Inbound Flights> <-- // flights at array position [1] of OriginDestinationOption
}]
},
...
The locations of the data for these in the JSON is:
Price: OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary[x].AirItineraryPricingInfo[0].ItinTotalFare.TotalFare.Amount;
Inbound: OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary[x].AirItinerary.OriginDestinationOptions.OriginDestinationOption[0]
Outbound: OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary[x].AirItinerary.OriginDestinationOptions.OriginDestinationOption[1]
With the current MongoDB release, the only way you can get results which are closer to what you want is by using the aggregation framework, and working on the premise that the OriginDestinationOption array will have two elememts, you'd need the $first and $last operators to select the first and last elements in the array after the $unwind operator. For now (based on the above assumptions) you may have to do with running this pipeline:
db.flights.aggregate([
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption" },
{
"$project": {
"Price": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo.ItinTotalFare.TotalFare.Amount",
"DestinationOptions": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption"
}
},
{
"$group": {
"_id": "$Price",
"Outbound" : { "$first": "$DestinationOptions" },
"Inbound" : { "$last": "$DestinationOptions" }
}
}
])
which will yield the result (from the sample data):
/* 1 */
{
"result" : [
{
"_id" : 269.56,
"Outbound" : {
"ElapsedTime" : 620,
"FlightSegment" : [
{
"DepartureDateTime" : "2015-11-12T11:40:00",
"ArrivalDateTime" : "2015-11-12T17:35:00",
"StopQuantity" : 0,
"FlightNumber" : "1980",
"ElapsedTime" : 235,
"DepartureAirport" : {
"LocationCode" : "LHR",
"TerminalID" : "2",
"content" : ""
},
"ArrivalAirport" : {
"LocationCode" : "IST",
"TerminalID" : "I",
"content" : ""
},
"OperatingAirline" : {
"Code" : "TK",
"FlightNumber" : "1980",
"content" : ""
}
},
{
"DepartureDateTime" : "2015-11-12T19:35:00",
"ArrivalDateTime" : "2015-11-13T02:00:00",
"StopQuantity" : 0,
"FlightNumber" : "760",
"ResBookDesigCode" : "W",
"ElapsedTime" : 265,
"DepartureAirport" : {
"LocationCode" : "IST",
"TerminalID" : "I",
"content" : ""
},
"ArrivalAirport" : {
"LocationCode" : "DXB",
"TerminalID" : "1",
"content" : ""
},
"OperatingAirline" : {
"Code" : "TK",
"FlightNumber" : "760",
"content" : ""
},
"Equipment" : [
{
"AirEquipType" : "343",
"content" : ""
}
],
"MarketingAirline" : {
"Code" : "TK",
"content" : ""
},
"MarriageGrp" : "I",
"DepartureTimeZone" : {
"GMTOffset" : 2
},
"ArrivalTimeZone" : {
"GMTOffset" : 4
},
"TPA_Extensions" : {
"eTicket" : {
"Ind" : true
}
}
}
]
},
"Inbound" : {
"ElapsedTime" : 730,
"FlightSegment" : [
{
"DepartureDateTime" : "2015-11-19T08:25:00",
"ArrivalDateTime" : "2015-11-19T11:40:00",
"StopQuantity" : 0,
"FlightNumber" : "763",
"ResBookDesigCode" : "W",
"ElapsedTime" : 315,
"DepartureAirport" : {
"LocationCode" : "DXB",
"TerminalID" : "1",
"content" : ""
},
"ArrivalAirport" : {
"LocationCode" : "IST",
"TerminalID" : "I",
"content" : ""
},
"OperatingAirline" : {
"Code" : "TK",
"FlightNumber" : "763",
"content" : ""
},
"Equipment" : [
{
"AirEquipType" : "330",
"content" : ""
}
],
"MarketingAirline" : {
"Code" : "TK",
"content" : ""
},
"MarriageGrp" : "O",
"DepartureTimeZone" : {
"GMTOffset" : 4
},
"ArrivalTimeZone" : {
"GMTOffset" : 2
},
"TPA_Extensions" : {
"eTicket" : {
"Ind" : true
}
}
},
{
"DepartureDateTime" : "2015-11-19T14:25:00",
"ArrivalDateTime" : "2015-11-19T16:35:00",
"StopQuantity" : 0,
"FlightNumber" : "1971",
"ResBookDesigCode" : "W",
"ElapsedTime" : 250,
"DepartureAirport" : {
"LocationCode" : "IST",
"TerminalID" : "I",
"content" : ""
},
"ArrivalAirport" : {
"LocationCode" : "LHR",
"TerminalID" : "2",
"content" : ""
},
"OperatingAirline" : {
"Code" : "TK",
"FlightNumber" : "1971",
"content" : ""
},
"Equipment" : [
{
"AirEquipType" : "32B",
"content" : ""
}
],
"MarketingAirline" : {
"Code" : "TK",
"content" : ""
},
"MarriageGrp" : "I",
"DepartureTimeZone" : {
"GMTOffset" : 2
},
"ArrivalTimeZone" : {
"GMTOffset" : 0
},
"TPA_Extensions" : {
"eTicket" : {
"Ind" : true
}
}
}
]
}
}
],
"ok" : 1
}
However, with the future releases (MongoDB 3.2 and newer), there are two operators $slice and $arrayElemAt which will work for you to produce the desired result. The $slice operator returns a subset of an array and the $arrayElemAt returns the element at the specified array index.
Thus you will implement the pipeline as follows -
Case 1. Using the $slice operator:
db.flights.aggregate([
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption" },
{
"$project": {
"Price": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo.ItinTotalFare.TotalFare.Amount",
"DestinationOptions": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption"
}
},
{
"$group": {
"_id": "$Price",
"DestinationOptions" : { "$push": "$DestinationOptions" }
}
},
{
"$project": {
"Inbound": { "$slice": [ "$DestinationOptions", 0, 1] },
"Outbound": { "$slice": [ "$DestinationOptions", 1, 1 ] },
"Price": "$_id",
"_id": 0
}
}
])
Case 2. Using the $arrayElemAt operator:
db.flights.aggregate([
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption" },
{
"$project": {
"Price": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo.ItinTotalFare.TotalFare.Amount",
"DestinationOptions": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption"
}
},
{
"$group": {
"_id": "$Price",
"DestinationOptions" : { "$push": "$DestinationOptions" }
}
},
{
"$project": {
"Inbound": { "$arrayElemAt": [ "$DestinationOptions", 0] },
"Outbound": { "$arrayElemAt": [ "$DestinationOptions", 1 ] },
"Price": "$_id",
"_id": 0
}
}
])
Here is my code in mongodb : .
db.mydb.aggregate([
{ "$group": {
"_id": {
"A": "$A",
"B": "$B",
"C": "$C"
},
}},
{ "$group": {
"cpt": { '$sum': 1 } ,
"_id": "$_id.A",
"allowDrag": {'$literal':false},
"expanded": {'$literal':false},
"children": {
"$push": {
"text": "$_id.B",
"details": "$_id.C",
"leaf": {'$literal': true},
}
},
}}
])
I would like to add in my json output some hardcoded properties and values, it works with
"leaf": {'$literal': true}
but I don't know why I can't make it with
"allowDrag": {'$literal':false},
"expanded": {'$literal':false}
is it possible with $group?
Example of the output json I've got :
"result" : [
{
"_id" : "A",
"cpt" : 1,
"children" : [
{
"text" : "B",
"details" : "C",
"leaf" : true
}
]
}]
Example of the output json I wish I had :
"result" : [
{
"_id" : "A",
"cpt" : 1,
"allowDrag" : false,
"expanded" : false,
"children" : [
{
"text" : "B",
"details" : "C",
"leaf" : true
}
]
}]
Use the $literal operator in the $project pipeline to return the new fields set to boolean values of false:
db.mydb.aggregate([
{
"$group": {
"_id": {
"A": "$A",
"B": "$B",
"C": "$C"
}
}
},
{
"$group": {
"cpt": { '$sum': 1 } ,
"_id": "$_id.A",
"children": {
"$push": {
"text": "$_id.B",
"details": "$_id.C",
"leaf": {'$literal': true}
}
}
}
},
{
"$project": {
"allowDrag": {'$literal':false},
"expanded": {'$literal':false},
"cpt": 1,
"children": 1
}
}
])
Tested with the following collection sample:
db.mydb.insert([
{
"A": "test1",
"B": "test2",
"C": "test3"
},
{
"A": "test1",
"B": "test2",
"C": "test2"
},
{
"A": "test2",
"B": "test2",
"C": "test3"
},
{
"A": "test2",
"B": "test2",
"C": "test3"
}
])
The above aggregation gives the following results:
/* 0 */
{
"result" : [
{
"_id" : "test1",
"cpt" : 2,
"children" : [
{
"text" : "test2",
"details" : "test2",
"leaf" : true
},
{
"text" : "test2",
"details" : "test3",
"leaf" : true
}
],
"allowDrag" : false,
"expanded" : false
},
{
"_id" : "test2",
"cpt" : 1,
"children" : [
{
"text" : "test2",
"details" : "test3",
"leaf" : true
}
],
"allowDrag" : false,
"expanded" : false
}
],
"ok" : 1
}
It is possible to select an item from the index which match multiple values for a certain sub-item? I think this is not so clear but I added more details below.
I have the following index:
{
"mappings" : {
"entity" : {
"properties" : {
"name" : {"type" : "string"},
"features" : {
"type" : "nested",
"include_in_parent" : false,
"properties" : {
"id" : {"type" : "integer"},
"value_int" : {"type" : "integer"},
"value_text" : {"type" : "string"},
"value_decimal" : {"type" : "integer"}
}
}
}
}
},
"settings" : {
"number_of_shards" : 1,
"number_of_replicas" : 0
}
}
Some items from the index
{
"name" : "Bazar",
"features" : [
{
"id" : 1,
"value_text" : null,
"value_decimal" : null,
"value_int": 51
},
{
"id" : 9,
"value_text" : "Amsterdam",
"value_decimal" : null,
"value_int": null
}
]
}
{
"name" : "Bazar Test",
"features" : [
{
"id" : 1,
"value_text" : null,
"value_decimal" : null,
"value_int": 52
},
{
"id" : 9,
"value_text" : "Leiden",
"value_decimal" : null,
"value_int": null
}
]
}
{
"name" : "Bazar no city",
"features" : [
{
"id" : 1,
"value_text" : null,
"value_decimal" : null,
"value_int": 51
},
]
}
What I need is a way to find just the items which have the features.id = 1 and features.id = 2 (ex: "Bazar" and "Bazar Test" items).
The query I got some far is
{
"query" : {
"nested" : {
"path" : "features",
"query" : {
"bool" : {
"must" : [
{ "terms" : { "features.id" : [1, 9]} }
]
}
}
}
}
}
The problem with this query is that it selects the items which have features.id = 1 OR features.id = 9 so all the items are returned.
Edit
Tried a new query
{
"query" : {
"nested" : {
"path" : "features",
"query" : {
"bool" : {
"must" : [
{ "terms" : {
"features.id" : [1, 9],
"minimum_should_match": 2
}
}
]
}
}
}
}
}
But I got no results.
Edit:
After I combined the answers, I managed to get it working.
Thank you for help :)
This is my query (a bit modified)
{
"from": 0,
"size": 20,
"query": {
"filtered": {
"query": {
"bool": {
"must": [
{
"match_phrase_prefix": {
"title": {
"query": "deli",
"max_expansions": 5
}
}
},
{
"match": {
"entity_type_id": 5
}
}
]
}
},
"filter": {
"and": {
"filters": [
{
"nested": {
"path": "features",
"query": {
"bool": {
"must": [
{
"match": {
"features.id": 31
}
},
{
"match": {
"features.value_int": {
"query": [
56, 57
],
"operator": "and"
}
}
}
]
}
}
}
}
]
}
}
}
}
}
Thank you.
The match query supports a Boolean operator parameter. You should also wrap the query in a nested query, as the features field is nested in your mapping.
Try this query:
{
"query": {
"nested": {
"query": {
"match": {
"features.id": {
"query": "1 9",
"operator": "and"
}
}
},
"path": "features"
}
}
}
Nested documents are more difficult to query. This should be what you want:
{
"query": {
"filtered": {
"filter": {
"and": {
"filters": [
{
"nested": {
"path": "features",
"query": {
"term": {
"features.id": {
"value": "1"
}
}
}
}
},
{
"nested": {
"path": "features",
"query": {
"term": {
"features.id": {
"value": "9"
}
}
}
}
}
]
}
}
}
}
}