How to get subarray from mongo document? [closed] - mongodb

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
How can I fetch a subarray from document?
Here is one of documents:
"director_details": {
"0": {
"AppointmentDate": "2010-06-02",
"AppointmentStatus": "CURRENT",
"AppointmentType": "SEC",
"NumAppointments": "1",
"Person": {
"CountryOfResidence": [],
"DOB": [],
"Forename": "MARK JHONSONE",
"Nationality": "NATIONALITY UNKNOWN",
"PersonAddress": {
"AddressLine": "5 PARSONS STREET",
"Country": [],
"County": "WEST MIDLANDS",
"PostTown": "DUDLEY",
"Postcode": "DY1 1JJ"
},
"PersonID": "CSeJxNkEELgkAQhe/9CvFerlpZsK0IFUSEUFZH2dyxlnK1XY3897mG5WV48/HezDDYf2cP4wVS8VwsTHuETANEkjMurgvzGK2HM9PwyQDfoW4qLQpV0rJSBGHr32he1gUQu6WtxIzLNJcgaAZkF+y3 [...]",
"Surname": "WESTWOOD",
"Title": "MR"
}
},
"1": {
"AppointmentDate": "2010-06-02",
"AppointmentStatus": "CURRENT",
"AppointmentType": "DIR",
"NumAppointments": "1",
"Occupation": "DIRECTOR",
"Person": {
"CountryOfResidence": "UNITED KINGDOM",
"DOB": "1979-11-30",
"Forename": "MARK DAVID",
"Nationality": "BRITISH",
"PersonAddress": {
"AddressLine": "5 PARSONS STREET",
"Country": [],
"County": "WEST MIDLANDS",
"PostTown": "DUDLEY",
"Postcode": "DY1 1JJ"
},
"PersonID": "CSeJxNkN0KgkAQhe97CvG+XCt/gm0jqCAihLK6lE3HWsp129XIt881TG+GMx9nZg6DF5/sabxBKpbzuWmPkGkAj/OE8dvcPIWboW8aCzLAD6jqSoVQBS1KRRC2ukbzohJAxg1tJE6YTHMJnGZA9svD [...]",
"Surname": "WESTWOOD",
"Title": "MR"
}
}
}
I want to search director which forename contains "david" and surname & title are not empty.
I have a query that works pretty fine, but it also returns extra subarray which I want to remove from output.

Ok. Suppose your document is:
{
"director_details": {
"0": {
"AppointmentDate": "2010-06-02",
...
},
"1": {
"AppointmentDate": "2010-06-02",
...
}
}
}
}
First of all, director_details in you question is not an array, it's an object. And director_details.Person.Forename: /david/ will not match by a couple of reasons:
Part of object's graph is missed, a path to Forename is director_details.1.Person.Forename.
Regexs in MongoDB are case sensitive by default, you should toggle i flag to make it case-insensitive.
The correct query that will match is: db.directors.find({"director_details.1.Person.Forename" : /DAVID/}). With current data model it is not flexible at all, as you need to specify 0 or 1.
Consider making director_details an array, like:
{
"director_details": [
{
"AppointmentDate": "2010-06-02",
...
},
{
"AppointmentDate": "2010-06-02",
...
}
]
}
In this case the query is very simple:
db.directors.find({}, {"director_details" : {$elemMatch : {"Person.Forename" : /DAVID/}}})
And here is the result of running it:
> db.directors.find({}, {"director_details" : {$elemMatch : {"Person.Forename" : /DAVID/}}}).pretty()
{
"_id" : ObjectId("52455db9cafed39bf0dee631"),
"director_details" : [
{
"AppointmentDate" : "2010-06-02",
"AppointmentStatus" : "CURRENT",
"AppointmentType" : "DIR",
"NumAppointments" : "1",
"Occupation" : "DIRECTOR",
"Person" : {
"CountryOfResidence" : "UNITED KINGDOM",
"DOB" : "1979-11-30",
"Forename" : "MARK DAVID",
"Nationality" : "BRITISH",
"PersonAddress" : {
"AddressLine" : "5 PARSONS STREET",
"Country" : [ ],
"County" : "WEST MIDLANDS",
"PostTown" : "DUDLEY",
"Postcode" : "DY1 1JJ"
},
"PersonID" : "CSeJxNkN0KgkAQhe97CvG+XCt/gm0jqCAihLK6lE3HWsp129XI",
"Surname" : "WESTWOOD",
"Title" : "MR"
}
}
]
}

Related

How can we rename a field or give alias to field in MongoDB Atlas charts?

How can we rename a field or give alias to field in MongoDB Atlas charts?
Examples:
this is the students collection
{
"_id": 1,
"alias": [ "The American Cincinnatus", "The American Fabius" ],
"mobile": "555-555-5555",
"nmae": { "first" : "george", "last" : "washington" }
},
{
"_id": 2,
"alias": [ "My dearest friend" ],
"mobile": "222-222-2222",
"nmae": { "first" : "abigail", "last" : "adams" }
}
Here I update the nmae field to name
db.students.updateMany( {}, { $rename: { "nmae": "name" } } )
{
"_id": 1,
"alias": [ "The American Cincinnatus", "The American Fabius" ],
"mobile": "555-555-5555",
"name": { "first" : "george", "last" : "washington" }
},
{
"_id" : 2,
"alias" : [ "My dearest friend" ],
"mobile" : "222-222-2222",
"name" : { "first" : "abigail", "last" : "adams" }
}
ref: https://docs.mongodb.com/manual/reference/operator/update/rename/

Getting an array out of the input using aggregate

My input file looks like this:
[
{
"type" : "asdf",
"properties" : {
"Name" : "First center",
"Code" : "ABCD",
"Address" : "Emmastr 14",
"City" : "Rotterdam",
"Postcode" : 55968,
}
},
{
"type" : "qwer",
"properties" : {
"Name" : "Second center",
"Code" : "OTHER",
"Address" : "Havenstraat 15",
"City" : "Rotterdam",
"Postcode" : 88767,
}
},
{
"type" : "zxcv",
"properties" : {
"Name" : "Third center",
"Code" : "ABCD",
"Address" : "Kerkstraat 16",
"City" : "Amsterdam",
"Postcode" : 33948,
}
},
{
"type" : "tyiu",
"properties" : {
"Name" : "Fourth center",
"Code" : "ABCD",
"Address" : "Zeestraat 17",
"City" : "Amsterdam",
"Postcode" : 56475,
}
}
]
I've been tasked to present this information grouped per city (a document for each city).
Only the items that have Code="ABCD" should appear in the output.
Output should be ordered by city name (_id).
Output should be written to a new collection.
So the output I'm looking for is something like this:
_id: "Amsterdam",
center: [
{"Name": "Third center" , "Postcode": 33948, "Address": "Kerkstraat 16"},
{"Name": "Fourth center" , "Postcode": 56475, "Address": "Zeestraat 17"}
]
_id: "Rotterdam",
center: [
{"Name": "First center" , "Postcode": 55968, "Address": "Emmastr 14"}
]
This little snippet filter by "ABCD", groups by city and writes the output to a new collection.
db.centers.aggregate ([
{$match: {"properties.Code": "ABCD"}}
,{ $group: {_id: "$properties.City"}}
,{ $out: "newColl"}
])
But I'm not getting much further because of lack of hands on experience.
I struggle getting an array out of something that's not an array in the input. Is there anyone that could help?
$push to make array of required fields
$sort by _id in ascending order
db.centers.aggregate([
{ $match: { "properties.Code": "ABCD" } },
{
$group: {
_id: "$properties.City",
center: {
$push: {
Name: "$properties.Name",
Postcode: "$properties.Postcode",
Address: "$properties.Address"
}
}
}
},
{ $sort: { _id: 1 } },
{ $out: "newColl" }
])
Playground

How to correct document validation fail in Mongodb?

Ive created the following collection(the creation of which is successful)
db.createCollection("Company", { "validator": { "$jsonSchema": {
"bsonType":"object",
"required":["city_name","city","street_name","building_number","budget","Department"],
"properties":{ "city_name":{ "bsonType":"string",
"description":"name of city" },
"city":{ "bsonType":"string",
"description":"City" },
"street_name":{ "bsonType":"string",
"description" :"name of street" },
"building_number":{"bsonType":"int",
"description":"number of building", minimum: 0, maximum: 500},
"budget":{"bsonType":"double",
"description":"budget of company",minimum: 0 },
"Department":{ "bsonType":"object",
"required":["Department_name","floor_number","Employee"],
"properties":{ "Department_name":{"bsonType":"string",
"description": "name of department" },
"floor_number":{"bsonType":"int",
"description":"number of floor" },
}},
"Employee":{ "bsonType":"object",
"required":["first_name","last_name","DOB","Salary"],
"properties":{"first_name":{"bsonType":"string",
"description":"Employees first name"},
"last_name":{"bsonType":"string",
"description":"Employees last name"},
"DOB":{"bsonType":"date",
"description":"Date of birth of empployee"},
"Salary":{"bsonType":"double",
"description":"Salary of Employee",minimum: 0},
"Position":{"bsonType":"string",
"description":"Position of employee. Field is not required"}}}}}}});
Ive created a set of data to insert into this collection to test the validations
db.Company.insert(
{ "city_name":"Sydney",
"city":"Sydney",
"street_name":"Pitt Street",
"building_number":100,
"budget": 100000.0,
"Department":{"department_name":"Google",
"floor_number":4,
"Employee" :{"first_name" : "George",
"last_name": "Martin",
"DOB": new Date('Dec 26,1981'),
"Salary" : "70000",
"Position": "CEO"}}
});
However when i run this script i get an error
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
Sadly Mongodb isnt very specific in what causes such errors and ive gone through my syntax and declarations and could not pick up on any errors myself,when clearly there is!
Why am i recieving this error when running my code? Thankyou
Try this:
01) Schema:
db.createCollection(
"Company",
{
"validator": {
"$jsonSchema": {
"bsonType":"object",
"required":["city_name","city","street_name","building_number","budget","Department"],
"properties": {
"city_name":{ "bsonType" : "string", "description" : "name of city" },
"city":{ "bsonType" : "string", "description" : "City" },
"street_name":{ "bsonType" : "string","description" : "name of street" },
"building_number": { "bsonType" : "int", "description" : "number of building", minimum: 0, maximum: 500},
"budget": { "bsonType" : "double", "description" : "budget of company",minimum: 0 },
"Department": {
"bsonType":"object",
"required":["Department_name","floor_number","Employee"],
"properties": {
"Department_name":{"bsonType":"string", "description": "name of department" },
"floor_number":{"bsonType":"int", "description":"number of floor" },
"Employee":{
"bsonType":"object",
"required":["first_name","last_name","DOB","Salary"],
"properties":{
"first_name":{"bsonType":"string", "description":"Employees first name"},
"last_name":{"bsonType":"string", "description":"Employees last name"},
"DOB":{"bsonType":"date", "description":"Date of birth of empployee"},
"Salary":{"bsonType":"double", "description":"Salary of Employee",minimum: 0},
"Position":{"bsonType":"string", "description":"Position of employee. Field is not required"}
}
}
}
},
}
}
}
}
);
02) Insert:
db.Company.insert(
{
"city_name": "Sydney",
"city": "Sydney",
"street_name": "Pitt Street",
"building_number": NumberInt(100),
"budget": 100000.0,
"Department":{
"Department_name":"Google",
"floor_number": NumberInt(4),
"Employee" : {
"first_name" : "George",
"last_name": "Martin",
"DOB": new Date('Dec 26,1981'),
"Salary" : 70000.0,
"Position": "CEO"
}
},
});
I have to do a few changes:
'int' fields have to be NumberInt(number) in the insert command.
The scheme has been changed so that 'Employee' is within 'Department'.
Salary must be double.
"Salary" : "70000" is an int, but the schema ask for double: "Salary":{"bsonType":"double", "description":"Salary of Employee",minimum: 0},.
I would recommend that you use the alias "bsonType":"number" in your schema instead of int,double, long, decimal. Since javascript is not typed, it can be a real pain to keep track which is used in your code.
See doc: https://docs.mongodb.com/manual/reference/operator/query/type/#available-types

MongoDB Return Inner Document From Array

I am trying to fetch an element from an array in a document and only the element I don't want the entire document
I tried a different method but they all return the entire document
db.dept.find({"section.classes.CRN":"1901"}).limit(100)
db.dept.where("section.classes.CRN").eq("1901").limit(100)
json
{
"_id" : ObjectId("5d70ab0c280d6b8ebb850cc1"),
"name" : "Art Studio",
"abbr" : "ARS",
"section" : [
{
"type" : "Undergraduate Courses",
"classes" : [
{
"CRN" : "193",
"Course" : "ARS100",
"Sec" : "01",
"Title" : "Drawing I",
"Cr" : "3",
"Dates" : "8/26-12/19",
"Days" : "MR",
"Time" : "1230P-0320P",
"Loc" : "SAB 226",
"Instructor" : "Schuck",
"Attributes" : "",
"Avail" : "F"
},
{
"CRN" : "293",
"Course" : "ARS100",
"Sec" : "02",
"Title" : "Drawing I",
"Cr" : "3",
"Dates" : "8/26-12/19",
"Days" : "MR",
"Time" : "0330P-0620P",
"Loc" : "SAB 226",
"Instructor" : "Itty",
"Attributes" : "",
"Avail" : "F"
},
{...
I am trying to get this or something similar when searching for a set of CRN values
json
[ {
"CRN" : "193",
"Course" : "ARS100",
"Sec" : "01",
"Title" : "Drawing I",
"Cr" : "3",
"Dates" : "8/26-12/19",
...
"Instructor" : "Schuck",
"Attributes" : "",
"Avail" : "F"
}
]
Try using the aggregate pipeline to project double nested array as:
Input:
[
{
"_id": ObjectId("5d70ab0c280d6b8ebb850cc1"),
"name": "Art Studio",
"abbr": "ARS",
"section": [
{
"type": "Undergraduate Courses",
"classes": [
{
"CRN": "193",
"Course": "ARS100",
"Sec": "01",
"Title": "Drawing I",
"Cr": "3",
"Dates": "8/26-12/19",
"Days": "MR",
"Time": "1230P-0320P",
"Loc": "SAB 226",
"Instructor": "Schuck",
"Attributes": "",
"Avail": "F"
},
{
"CRN": "293",
"Course": "ARS100",
"Sec": "02",
"Title": "Drawing I",
"Cr": "3",
"Dates": "8/26-12/19",
"Days": "MR",
"Time": "0330P-0620P",
"Loc": "SAB 226",
"Instructor": "Itty",
"Attributes": "",
"Avail": "F"
}
]
}
]
}
]
Query:
hereafter unwinding section you can filter classes for CRN
db.collection.aggregate([
{
$unwind: "$section"
},
{
$project: {
name: 1,
abbr: 1,
"section.type": 1,
"section.classes": {
$filter: {
input: "$section.classes",
as: "item",
cond: {
$eq: [
"$$item.CRN",
"193"
]
}
}
}
}
},
{
$group: {
_id: "$_id",
section: {
$push: "$section"
}
}
}
])
Output:
you can manage your keys as you want in project for adding new keys or replacing them.
[
{
"_id": ObjectId("5d70ab0c280d6b8ebb850cc1"),
"section": [
{
"classes": [
{
"Attributes": "",
"Avail": "F",
"CRN": "193",
"Course": "ARS100",
"Cr": "3",
"Dates": "8/26-12/19",
"Days": "MR",
"Instructor": "Schuck",
"Loc": "SAB 226",
"Sec": "01",
"Time": "1230P-0320P",
"Title": "Drawing I"
}
],
"type": "Undergraduate Courses"
}
]
}
]
db.dept.find({"section.classes.CRN":"1901"},{"section.classes":1}).limit(100)
It's called projection in mongodb, you pass a second object in find query to specify which fields you want in result.
so according to your above case if you want name, and section in result you should pass something like this
db.dept.find({"section.classes.CRN":"1901"},{"name":1, "section":1}).limit(100)

mongodb find element in array or less but no other

I have this collection:
{
"title": "First Item",
"attributes": [
{
"id": "1",
"text": "Alpha"
},
{
"id": "2",
"text": "Bravo"
},
{
"id": "3",
"text": "Charlie"
}
]
},
{
"title": "Second Item",
"attributes": [
{
"id": "1",
"text": "Alpha"
},
{
"id": "2",
"text": "Bravo"
},
{
"id": "3",
"text": "Tango"
}
]
}
Trying search with these values for "attributes.text" field:
{ "Alpha", "Bravo", "Charlie", "Delta" }
I want to find only "First Item" document that contains at least these keys but no others.
But trying these values:
{ "Alpha", "Bravo", "Delta" }
or
{ "Alpha", "Bravo" }
I do not want to find any result (beacuse "Charlie" is missing).
Thank you
Use the $in operator to match values in the attributes object array. The following query will select all documents in the collection where the text field value of the attribute object array is either "Alpha", "Bravo" or "Delta":
dbo.collection.find({
"attributes.text": {
"$in": ["Alpha", "Bravo", "Delta"]
}
});
This will return the two documents:
/* 0 */
{
"_id" : ObjectId("551187bae3757367bf8bd915"),
"title" : "First Item",
"attributes" : [
{
"id" : "1",
"text" : "Alpha"
},
{
"id" : "2",
"text" : "Bravo"
},
{
"id" : "3",
"text" : "Charlie"
}
]
}
/* 1 */
{
"_id" : ObjectId("551187bae3757367bf8bd916"),
"title" : "Second Item",
"attributes" : [
{
"id" : "1",
"text" : "Alpha"
},
{
"id" : "2",
"text" : "Bravo"
},
{
"id" : "3",
"text" : "Tango"
}
]
}