how to set a key,value in a mongo array - arrays

I have a collection of students where they can have other students as friends
{name:'someone', email:'st', friends[ObjectId,ObjectId]}
To access the list of friends I'll have to populate that object and search inside all the objects of the array friends
this will take mutch time
What I would like to do is this:
collection.find({name:'someone'},function(err,obj){
if(obj['user1'])
//do st
else
//do st
})
this will reuire that i insert objects like this:
collection.find({name:'st'},function(err,obj){
obj.friends['some one']=ObjectId(of an other student)
})
but this last one is not working

You can easily accomplish this if you use Mongoose in addition to Mongo. In your students schema you need an Array of friends which will be just the ID's of other students:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var StudentSchema = new Schema({
name: String,
friends: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Student' }]
});
module.exports = mongoose.model('Student', StudentSchema);
Then when adding a friend all you need to do is push the ID of that friend into the array of friends.
Once the collection stores the relationship properly you can use mongoose's populate method to actual fill in the data in your API end point.. Something like this:
app.get('/student/:id, function(req, res){
Student.find({_id: req.params.id})
.populate('friends')
.exec(function(err, student){
if(err){
// handle error
} else {
res.json(student)
}
})
});

Related

Collection is not getting created even after creating the model using mongoose

I have created a model using mongoose.
However, it is not creating collection in mongodb.
My connection is working fine though to the mongodb
var mongoose = require("mongoose"),
Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
const conn = require('app/connection');
var notesSchema = new Schema({
_id: ObjectId,
message: String,
});
var dataSchema = new Schema({
_id: ObjectId,
dataId: String,
dataName: String,
notes: [notesSchema]
}, {
collection: 'dataCols'
});
var dataCol = conn.on('cg').model('dataCol', dataSchema);
I have also tried acting against the model (find, insert etc) but the collection is not created automatically.
I am connecting to a replica set

Mongoose doesn't create subdocument from JSON array

I'm trying to write a JSON object that contains both first-level data along with arrays into MongoDB.
What happens instead is all first-level data is stored, but anything contained in an array isn't. When logging the data the server receives, I see the entire object, which leads me to believe there's something wrong with my Mongoose code.
So for example if I send something like this:
issueId: "test1",
issueTitle: "testtest",
rows: [
{order:1,data: [object]},
{order:2,data: [object]},
]
Only the following gets stored:
issueId: "test1",
issueTitle: "testtest",
lastUpdated: Date,
I have the following model for Mongo:
//model.js
var mongoose = require('mongoose');
var model = mongoose.Schema({
issueId : String,
issueTitle : String,
lastUpdated : {type: Date, default : Date.now},
rows : [{
order : Number,
data : [
{
title : String,
text : String,
link : String,
}
]
}]
});
module.exports = mongoose.model('Model', model);
And the routing code, where I believe the problem likely is:
//routes.js
const mongoose = require('mongoose');
const Model = require('./model.js');
...
app.post('/api/data/update', function(req, res) {
let theData = req.body.dataToInsert;
console.log(JSON.stringify(theData,null,4));
Model.findOneAndUpdate(
{issueId : theData.issueId},
{theData},
{upsert: true},
function(err,doc){
if(err) throw err;
console.log(doc);
});
});
As well, here's the part of the Angular controller storing the data. I don't think there's any problem here.
pushToServer = function() {
$http.post('/api/data/update',{
dataToInsert : $scope.dataObject,
}).then(function successCallback(res){
console.log("all good", JSON.stringify(res,null,3));
}, function errorCallback(res){
console.log("arg" + res);
});
}
Look at the first question in the mongoose FAQ:
http://mongoosejs.com/docs/faq.html
Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to use MongooseArray#set available in Mongoose >= 3.2.0.
// query the document you want to update
// set the individual indexes you want to update
// save the document
doc.array.set(3, 'changed');
doc.save();
EDIT
I think this would work to update all of the rows. I'd be interested to know if it does work.
let rowQueries = [];
theData.rows.forEach(row => {
let query = Model.findOneAndUpdate({
issueId: theData.issueId,
'row._id': row._id
}, {
$set: {
'row.$': row
}
});
rowQueries.push(query.exec());
});
Promise.all(rowQueries).then(updatedDocs => {
// updated
});

Mongoose search data by object

I want to make a search in database by JSON objects.
Here is my schema:
var patientSchema = new Schema({
firstname: String,
lastname: String,
age: String,
tel: String,
work: [workSchema],
});
My angular js request, sends an JSON object which will be:
{'firstname':'value', 'lastname':'value', 'age':'age','tel':tel}
Is there a way to search for the matches directly in the Patient Schema?
so if the JSON object contains only firstname value .. it will check that
in MySQL I would do,
SELECT * FROM patients WHERE firstname LIKE '%'.json.firstname AND .....
what I've tested is
var filter = "{'firstname': 'value', 'lastname': 'value', 'age':'value', 'tel': 'tel'}" //sent from angularjs client
var jsonFilter = JSON.parse(filter);
Patient.find().or([
{ 'firstname': { $regex: new RegExp(filter.firstname,'i') }},
{ 'lastname': { $regex: new RegExp(filter.lastname,'i') }},
{ 'age':{ $regex: new RegExp(filter.age,'i') }},
{ 'tel':{$regex: new RegExp(filter.tel,'i') }}]).exec(function(err, result) {
if ( err)
throw err;
res.json(result);
});
this works fine but ALL the data should be filled if the attributes are empty it will return undefined which will not get me the right data. since Angular JS sends only the $scope.data.
Is there a way to get all the data by my JSON object, and not rewriting all the JSON fields, because I need to make bigger filters in this project?
I do not know if it is the best way to do this, but it is a start. I would loop over your keys and build your query dynamically. By looping over your keys, you can add as many keys as you want. For each key, push your new regex to your query variable. Finally, use your result as query.
Here is the code:
var filter = {'firstname': 'value', 'lastname': 'value', 'age':'value', 'tel': 'tel'};
var query = {$or: []};
var keys = Object.keys(filter);
for(var i=0;i<keys.length;i++) {
var item = {};
item[keys[i]] = new RegExp(filter[key], 'i');
query.$or.push(item);
}
Patient.find(query).exec(function(err, result) {
if ( err)
throw err;
res.json(result);
});

Mongoose schema array with extra ids [duplicate]

This question already has an answer here:
Why is an _id with ObjectID added to when using MongoDB's $push to add new object to an array?
(1 answer)
Closed 9 years ago.
I have the following Mongoose schema for a node js app I'm working on:
var memory = new schema({
date_added: Date,
name: String,
description: String,
personsInvolved: [{person: String}],
location: String,
uniqueness: Number,
category: String
});
It has an array field called personsInvolved that just has one field in it, person.
In my app, there's a form that takes a list of people, separated by a comma and it goes to a create function that takes that value and splits it on the commas into an array.
That part works, but it adds an _id field to each person in the array when I save the document into mongo. It looks like this:
personsInvolved:
[ { person: 'Test', _id: 52c6d6c2457e5ce02b00000b },
{ person: ' test2', _id: 52c6d6c2457e5ce02b00000c },
{ person: ' test3', _id: 52c6d6c2457e5ce02b00000d } ] }
Is there a way to make it so the _id field doesn't get added to each person? This is the code I'm using to save the record to mongo:
exports.create = function(req, res) {
// people are separated by a comma
var people = req.body.people;
var peopleArr = req.body.people.split(",");
var newMem = new memory();
newMem.date_added = Date.now();
newMem.name = req.body.name;
newMem.description = req.body.description;
for(var i in peopleArr) {
var name = {person: peopleArr[i]};
newMem.personsInvolved.push(name);
}
newMem.location = req.body.location;
newMem.uniqueness = req.body.uniqueness;
newMem.category = req.body.category;
console.log(newMem);
newMem.save(function(err, memory, count) {
res.redirect('/');
});
};
I'm only using personsInvolved as data, the persons in the array are not being used to identify with any other documents.
Make person a real schema model (as opposed to an anonymous object) and pass it {_id:false}.
http://mongoosejs.com/docs/subdocs.html

How to query mongoose by property that is and array item

I have a mongoose model that looks like this:
var mongoose = require('mongoose')
, Schema = mongoose.Schema;
var PictureSchema = new Schema({
listId: { type: Array, required: true },
thumb: { type: String, required: true },
large: { type: String, required: true }
});
var Picture = module.exports = mongoose.model('Picture', PictureSchema);
I am trying to update instances of this model in my router by looking up a Picture via the "listId" property. Like this:
app.put('/pictures/append', function(req, res) {
var targetListId = req.body.targetListId
, currentListId = req.body.currentListId;
Picture
.find({ listId: currentListId }, function (err, picture) {
console.log('found pic', picture);
picture.listId.push(targetListId);
picture.save(function(err, pic) {
console.log('pic SAVED', pic);
});
});
});
"currentListId" is a string, and listId is an array of currentListId's. Maybe this isn't the correct way to query a a property that is an array?
I am getting an error:
TypeError: Cannot call method 'push' of undefined
On the line:
picture.listId.push(targetListId);
But when I look up the picture models in mongo, they DO have listId arrays and some DO contain the item "currentListId" that I am using for my query.
I tried using $elemMatch and $in but I don't know if I was using them correctly.
Any idea if I am just writing my query wrong?
Specifying an Array typed field in your schema is equivalent to Mixed which tells Mongoose that field could contain anything. Instead, change your schema to something like this:
var PictureSchema = new Schema({
listId: [String],
thumb: { type: String, required: true },
large: { type: String, required: true }
});

Resources