问题
I am new to MongoDB and trying to execute a query to find a matching text from a database. Below are the details mentioned -
Using MongoDB, I am trying to fetch the annotated texts having remarks as DATA NOT FOUND. With my query, I am getting all the records having remarks as DATA NOT FOUND as well as remarks as TOO_MANY_DATA. Please refer to the below data present in the database-
Input-
{
"_id" : ObjectId("aaaaaaaaaaaa"),
"projectDR" : "123456789",
"code" : "RRR",
"fileName" : "123456789_1.xml",
"specFileDivNumber" : "050000",
"normalizationStatus" : "ASDWFGL",
"divisionIn" : {
"sections" : [
{
"sectionNumber" : "050000",
"sectionName" : "textile",
"labels" : [
{
"normalizedDate" : ISODate("2018-10-28"),
"remarks" : "DATA NOT FOUND",
"bod" : false,
"ID" : "4048",
"annotatedText" : "Mains"
},
{
"normalizedDate" : ISODate("2018-10-28"),
"remarks" : "DATA NOT FOUND",
"bod" : false,
"ID" : "4064",
"annotatedText" : "routong"
},
{
"prefCode" : "ABC00000890",
"prefLabel" : "ABCRTYYUUUU",
"normalizedDate" : ISODate("2018-10-28"),
"remarks" : "TOO_MANY_DATA",
"bod" : false,
"ID" : "15736",
"annotatedText" : "Uniform"
},
]
}
]
},
"status" : "Success",
"fileDate" : ISODate("2018-10-28"),
"Type" : "History"
}
Query-db.getCollection('BasicInfo').find({'divisionIn.sections.labels.remarks':'DATA NOT FOUND'})
Expected output:
{
"_id" : ObjectId("aaaaaaaaaaaa"),
"projectDR" : "123456789",
"code" : "RRR",
"fileName" : "123456789_1.xml",
"specFileDivNumber" : "050000",
"normalizationStatus" : "ASDWFGL",
"divisionIn" : {
"sections" : [
{
"sectionNumber" : "050000",
"sectionName" : "textile",
"labels" : [
{
"normalizedDate" : ISODate("2018-10-28"),
"remarks" : "DATA NOT FOUND",
"bod" : false,
"ID" : "4048",
"annotatedText" : "Mains"
},
{
"normalizedDate" : ISODate("2018-10-28"),
"remarks" : "DATA NOT FOUND",
"bod" : false,
"ID" : "4064",
"annotatedText" : "routong"
},
]
}
]
},
"status" : "Success",
"fileDate" : ISODate("2018-10-28"),
"Type" : "History"
}
Please help me to correct the query so as to get the expected.
回答1:
This is a standard and understandable array-of-array misconception with MongoDB. The query criteria will yield the proper result scoped to a document, not necessarily just the items in an array you are looking for. In other words, given your desired goal of finding DATA NOT FOUND, most simple queries will find any document where at least one item in the array matches -- but will not filter out those that do not. You have to get a little more complex to do this in one shot:
db.foo.aggregate([
// Make sure at *least* one label has a remark of DATA NOT FOUND;
// otherwise, the $filter trick in the next stage yields a labels array
// of length 0 (which is not horrible). Also, this is a good place to
// add other $match criteria, possibly index-optimized, to shrink down the
// size of response set:
{$match: {"divisionIn.sections.labels.remarks":"DATA NOT FOUND"}}
,{$project: {
// Copy over the main doc level things we want:
projectDR: "$projectDR",
code: "$code",
status: "$status"
// divisionIn is a map, not an array, so we can dive down using dot notation
// and make a new sections array called divSections that will ONLY have
// DATA NOT FOUND:
divSections: {$map: {input: "$divisionIn.sections", as:"z", in:
{
// Again, copy over things we want to keep; may not need all of them
"sectionNumber": "$$z.sectionNumber",
"sectionName": "$$z.sectionName",
// The Juice: Copy BUT FILTER the labels field conditionally based on
// the value of labels.remarks:
"labels": {$filter: {input: "$$z.labels",
as: "z2",
cond: {$eq: [ "$$z2.remarks", "DATA NOT FOUND"] }
}}
}
}}
}}
]);
来源:https://stackoverflow.com/questions/59492131/mongodb-fetching-exact-array-element-excluding-others