Inserting a Document As a Field - mongodb

Let' say I have a company collection:
[{
name: 'x',
code: 'a',
},
{
name: 'y',
code: 'b',
}]
I want to find the company with code 'a' and insert this to another collection called projects. I wrote something like this:
var collectionP = db.collection('projects');
var collectionC = db.collection('company');
var foundCompany = collectionC.find({code: 'a'});
db.collectionP.insert(name: 'project1', company: foundCompany);
This doesn't work. Any idea?

Calling find returns a cursor, not a result set.
Your alternatives are either iterate over the cursor, if expecting multiple results:
var foundCompany = collectionC.find({code: 'a'});
foundCompany.forEach(function(fc) {
db.collectionP.insert(name: 'project1', company: fc);
}
or convert it into an array if you want all results in one document:
var foundCompany = collectionC.find({code: 'a'}).toArray();
db.collectionP.insert(name: 'project1', company: foundCompany);
or if you only expect to match a single company, use findOne or its equivalent in your language:
var foundCompany = collectionC.findOne({code: 'a'});
db.collectionP.insert(name: 'project1', company: foundCompany);

Related

BelongsTo in Sails.js

Hello, I need your help please with 2 questions.
I have 2 Models
One to Many
(One) Customer{ id, names, dni} -> Invoice {id, date, ....customer_id} (Many)
1. How can I get this?
I need to consume the api "GET /api/invoices" and that the json return of this, in turn, returns an array
[{
id: 1,
date: '2022-01-01',
....invoice
customer: {
dni: 1,
names: 'Example'
}
},
{
id: 2,
date: '2022-01-02',
....invoice
customer: {
dni: 2,
names: 'Example 2'
}
},
]
So far what I have found in the sailsjs documentation are only examples with POPULATE, where they only show how to list the User model with its corresponding created ones (hasMany)
//var users = await User.find().populate('pets');
// The users object would look something like the following
// [{
// id: 123,
// firstName: 'Foo',
// lastName: 'Bar',
// pets: [{
// id: 1,
// breed: 'labrador',
// type: 'dog',
// name: 'fido',
// user: 123
// }]
// }]
//---This is not what I need.
Is there a function or configuration that I have not found?
Or would I do something like this?
Invoices.find().exec(async(err, invoices)=>{
if(invoices){
for(i = 0; i< invoices.length; i++){
const customer = await Customer.find({id: invoices[i].customer_id});
invoices[i].customer = customer;
}
});
The point is that this takes much longer than doing a query with join
const invoices = await sails.sendNativeQuery('SELECT * from INVOICE A A inner join CUSTOMER B on A.customer_id=B.id ', []);
But I don't know how to get a JSON with the previous structure if I do it by query
2. What is the best option that can solve my problem?
The populate method works in both directions: oneToMany, manyToMany, and manyToOne:
https://sailsjs.com/documentation/reference/waterline-orm/queries/populate
If any condition is required, you could check the details on the section Populating a collection association:
var usersNamedFinn = await User.find({ name:'Finn' })
.populate('currentSwords', {
where: {
color: 'purple'
},
limit: 3,
sort: 'hipness DESC'
});

MongoDB - Is it possible to write several different functions in MapReduce?

As part of my studies, we recently started learning MongoDB, and so I am very young in the field.
In one of the tasks we have been assigned to, MapReduce is used, but I can not do it properly.
Giving a collection of students of the following form:
{
_id: ObjectId("4ffmdjd8cfd99k03"),
tz: "11111",
FirstName: "Anton",
LastName: "Gill",
Department: "Computer Science"
Year: 1
Courses: [ { name: "Linear Algebra 1", grade: 70}, {name: "OS", grade: 88}]
}
The task is to write a mapReduce function, so that it returns a list of the names of the students in each department and each year, all whose grades are greater than 90. Example of normal output:
[{Department: "Computer Science", Year: 1, students: ["Anton", "John"]},
{Department: "Physics", Year: 2, students: ["Dean", "David"]}]
Can I write more than one map function? That is, the mapReduce structure will look like this:
db.students.mapReduce(
map1,
map2,
map3,
..
reduce,
..
I try unsuccessfully to create the desired structure.
This is the best I've been able to get to, and I'm still not sure how to write the reduce function.
var map = function(){
var value = 0, n = this.Courses.length;
for(var i = 0; i < n; i++){
value += this.Courses[i].grade;
}
var avgGrade = value/n;
if(avgGrade > 90){
var key = {
tz:this.tz,
Department:this.Department,
Year:this.Year,
};
value = {students:[this.FirstName]};
}
emit(key, value);
};
var reduce = function(keysObj, valuesObj){
return 1000; //Ignore this function, I've no idea how to deal with it.
};
db.students.mapReduce(
map,
reduce,
{
out: "output",
}
)
I would highly appreciate any assistance :)

Embedding fields in all mongodb documents

I have a collection with documents that follows this structure:
child:
{
id: int
name: string
age: int
dob: date
school: string
class: string
}
I would like to embed certain fields, into something like this:
child:
{
id : int
personalInfo {
name: string
age: int
dob: date
}
educationInfo {
school: string
class: string
}
}
How would one go across in doing this in code? I am new to Mongodb, so I apologize if my syntax is incorrect. All of the fields have one-to-one relationships with the child (i.e. one child has one id, one name, one age, one school etc.), so I'm also wondering if embedding is even necessary.
Please try to use $set to set the new field personalInfo and educationInfo, with #unset to remove old fields age, name etc. Before do it, it would be better to check all those fields exists through $exists, here are sample codes as below,
> var personfields = [ "name", "age", "dob" ];
> var educationFields = [ "school", "class" ];
> var query = {};
> personFields.forEach(function(k){ query[k] = {$exists: 1}});
> educationFields.forEach(function(k){ query[k] = {$exists: 1}});
> db.collection.find(query).forEach(function(doc){
var personalInfo = {};
var educationInfo = {};
for (var k in doc) {
if (personFields.indexOf(k) !== -1){
personalInfo[k] = doc[k];
} else if (educationFields.indexOf(k) !== -1) {
educationInfo[k] = doc[k];
}
}
db.collection.update({_id: doc._id},
{$set: {
personalInfo: personalInfo,
educationInfo: educationInfo},
$unset: {'name': '',
'age': '',
'dob': '',
'school': '',
'class': ''}});
})
It's OK to embed them, that's what document dB's are for. So if you need a migration, you'll basically use mongodb's functions like update ,with $set and $unset.
See more here: https://docs.mongodb.org/manual/reference/method/db.collection.update/

Adding to an array of lists in mongodb?

Silly question here, but I'm having trouble finding an example on the web.
I have set up a model on mongoDB that has arrays of objects, like so:
var ProjectSchema = new Schema({
project_id: { type: String },
item: {
title: { type: String },
owners: [{
first_name : {type: String} ,
middle_name : {type: String},
other_name: {type: String},
last_name: {type: String},
order: {type: Number, 'default': 1}
}]
}
}]
So you can see that item is a list of fields. And then owners is an array of lists of fields. When I create the project, I'm trying to set the owner like this:
var newProject = new Models.Project({
'item.title': title,
'item.owners[0].last_name': name,
'item.owners[0].order': 1
});
This doesn't generate an error, but the item fields don't get saved either (item.title saves fine).
I tried this too, but it gives me an error:
var newProject = new Models.Project({
'item.title': title,
item.owners.push({last_name: name, order: 1})
});
How am I supposed to refer to these sub-docs so I can save them?
Don't use dot notation in the fields of a new document, create it using the actual structure of the doc instead:
var newProject = new Models.Project({
item: {
title: title,
owners: [{
last_name: name,
order: 1
}]
});
it is a simple JSON object. With Javascript, it is quite straight forward. Below code generates the sample object given in the mongoDB doc:
var address1 = new Object();
address1.street = "123 Fake Street";
address1.city = "Faketon";
address1.state = "MA";
address1.zip = "12345";
var address2 = new Object();
address2.street = "1 Some other Street";
address2.city = "Boston";
address2.state = "MA";
address2.zip = "12345";
var data = new Object();
data._id = "joe";
data.name = "Joe Bookreader";
var addressArray = new Array();
addressArray.push(address1);
addressArray.push(address2);
data.addresses = addressArray;
alert(JSON.stringify(data));

MongoDB: How to compare two documents?

For example I have this collection:
Posts = new Mongo.Collection('posts');
Posts.insert({
name: "One",
age: 25,
...etc.
});
Posts.insert({
name: "Two",
age: 29,
...etc.
});
And how i can compare my first insert document with the second ??
I try to search about it but all I can found is "How to compare fields" not all document
ADD :
How to get true if my collection (Posts) contains my first insert document, with or without Underscore.js ?
Posts.insert({
name: "One",
age: 25,
...etc.
});
To compare if two documents are "equal" you can use underscore's _.isEqual like this:
var postId1 = Posts.insert({...});
var postId2 = Posts.insert({...});
var post1 = Posts.findOne(postId1);
var post2 = Posts.findOne(postId2);
console.log(_.isEqual(post1, post2));