Mongoose schema array with extra ids [duplicate] - arrays

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

Related

Create an object array from another object array and reconstruct the original object array later using map

Consider the following classes
class Category {
var tag: String?
var itemList: [Item]?
}
class Item {
var id: Int?
var type: String?
var itemDetails: ItemDetails?
}
class ItemDetails {
var description: String?
var name: String?
var price: Float?
}
Given an array of Category objects.
var categoryList: [Category]
I want to create a new object array by extracting only the name in ItemDetails(inorder to apply a filter) and an id inorder to reconstruct back array of Category objects.
Hence, I have to reconstruct the array of Category objects
from new object array.
How to do both extraction and reconstruction using the map feature?
Below are the examples of other data sources:
Datasource 1 :
var categoryList: [Category], where name need to be extracted
Datasource 2 :
var searchList = [SearchItem], where title to be extracted.
Class SearchItem {
var id: Int?
var details: SearchItemDetails?
var type: String?
}
Class SearchItemDetails {
var description: String?
var title: String?
}
DataSource 3
var products: [Products], where title to be extracted.
Class Products {
var id: Int?
var details: ProductDetails?
var type: String?
}
class ProductDetails {
var description: String?
var title: String?
}
To get an array of just the names, you do the map like you mentioned:
let categories: [Category] = ... // this already exists
let itemNames = categories.map { $0.itemList?.map({ $0.itemDetails?.name }) }
But this will preserve optionals. If you don't want optionals, then use compactMap instead.
Reconstructing, however, doesn't really make any sense. Are you using the ID to hit a database or network service? That's the only possible way you'd be able to reconstruct the original array of Categorys. Why not just hold onto the original array?

Add a Property to an Array of Objects from a Mongoose Find() query [duplicate]

This question already has answers here:
Why can't you modify the data returned by a Mongoose Query (ex: findById)
(3 answers)
Closed 4 years ago.
I am returning an array of document objects from a Mongoose query. The array is populated with expected results.
[{
_id: 1,
name: 'Mayonnaise'
},
{
_id: 2,
name: 'Gravy'
}]
I am trying to add a new property on to certain objects only where a criteria is met. I've tested this element and the conditional logic is also performing as expected. I loop through the array above and another, larger array to find matching ids. When a match is found, I need to add a property, for example:
{isArchived: true}
to the object in the array returned by the find() query. So I should end up with:
[{
_id: 1,
name: 'Mayonnaise'
},
{
_id: 2,
name: 'Gravy',
isArchived: true
}]
The problem is that no matter what I try I cannot get the new property added onto the specific object within the array.
I have tried just about every 'Add property to an object' answer on here, so am just about ready to start throwing things!!
Thanks for any and all help!
EDIT: The entire router code is as follows:
router.get('/edit/:id', ensureAuthenticated, (req, res) => {
Menu.findOne({ _id: req.params.id })
.populate('recipes')
.then(menu => {
Recipe.find({user: req.user.id}, function (err, allRecipes) {
if(menu.user != req.user.id){
req.flash('error_msg', 'Not Authorised!');
res.redirect('/menus');
} else {
//use momentjs to format dates to YYYY-MM-DD
const vFromDate = moment(menu.validFrom).format('YYYY-DD-MM');
const vToDate = moment(menu.validTo).format('YYYY-DD-MM');
const selectedRecipeIds = menu.recipes.map(id => id._id);
for (var i = 0; i < allRecipes.length; i++){
for (var j = 0; j < selectedRecipeIds.length; j++){
if (JSON.stringify(allRecipes[i]._id) == JSON.stringify(selectedRecipeIds[j]._id)) {
allRecipes[i].isSelected = true
}
}
}
res.render('menus/edit', {
menu,
vFromDate,
vToDate,
allRecipes
});
}
});
})
});
a = [{
_id: 1,
name: 'Mayonnaise'
},
{
_id: 2,
name: 'Gravy'
}]
a[0].isArchived = true
I think you are trying to mutate the original objects that came from the response.
Try to operate on a copy, like this:
const allRecipiesCopy = [...allRecipies]
And then loop over this array, and mutate these objects, not original ones.

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
});

how to set a key,value in a mongo array

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)
}
})
});

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);
});

Resources