Mongoose schema updating GeoJSON - node.js

I have the following Mongoose schema representing a moving object
var vehicleSchema = new Schema({
properties:{
obj:String,
name:String,
id:String
},
geometry : {
type: {type : String},
coordinates : [ Number, Number ]
}
});
and I am trying to update it with the following object and command which work flawlessly if I enter in mongo console but does not update the document when used in a node function.
This is the object to be updated:
var updatedVehicle = new Vehicle(
{properties:{
obj:"Answer",
name:"is",
id:"42"
},
geometry:{
type:"Point",
coordinates:[42,42]
}
})
And this is the update command
Vehicle.update(
{$and:[
{'properties.obj':data.properties.obj},
{'properties.id':data.properties.id}
]},
{$set:
{properties:data.properties, geometry:data.geometry}
},
{upsert: true},
cb
)
I know that Mongoose has some quirks when it comes to GeoJSON and I hope this is just another one.

Your geometry schema property should just be set to an array of Numbers to store the coordinates, like so:
geometry : {
type: [Number],
index: '2dsphere` //some geospatial queries require this
}
and then query and updated as such
{ $set: { geometry: data.geometry.coordinates } }

Related

Mongoose populate not working as expected

I am very much new in using mongoose and had done simple db work on mongodb.
Seeing my usecase I found this method of doing it in mongodb using mongoose. However I am not getting expected result as shown in tutorials.
My Schemas
var EventsSchema = new mongoose.Schema({
root: {type: mongoose.Schema.Types.ObjectId, ref: 'root'},
voting: [{type: mongoose.Schema.Types.ObjectId, ref: 'Voting'}]
});
var VotingSchema = new mongoose.Schema({
events: {type: mongoose.Schema.Types.ObjectId, ref: 'Events'},
title: {
type: String,
required: true
}
})
var Events = mongoose.model('Events', EventsSchema, 'event');
var Voting = mongoose.model('Voting', VotingSchema, 'voting');
I have these two schemas initially. I want to create a voting event. When voting event is created then in voting schema events id should be stored as suggested and more I want is that voting event reference should be stored in EventSchema.
var events = new Events({});
events.save()
.then((events) => {
var voting = new Voting({ events: events._id, title: "Test Title" });
voting.save()
.then((voting) => {
Voting.findOne({title: 'Test Title'})
.populate('events')
.exec(function(err, voting){
console.log(voting, err);
if(err) res.sendStatus(401).send();
else res.sendStatus(200).send();
})
})
.catch((e) => {
res.sendStatus(401).send();
});
})
.catch((e) => {
res.sendStatus(401).send();
})
What I am getting on console is
{
_id: 5b83eca82a3cfb1dec21ddc9,
events: { voting: [], _id: 5b83eca82a3cfb1dec21ddc8, __v: 0 },
title: 'Test Title',
__v: 0
}
My MongoDB looks like this
voting
{
"_id" : ObjectId("5b83eca82a3cfb1dec21ddc9"),
"events" : ObjectId("5b83eca82a3cfb1dec21ddc8"),
"title" : "Test Title",
"__v" : 0
}
events
{
"_id" : ObjectId("5b83eca82a3cfb1dec21ddc8"),
"voting" : [],
"__v" : 0
}
I am not sure how will my mongodb look like. But after attempting the code once it looks like above.
I must be doing something wrong or missing something important. But this kind of code is there in docs too. docs link. Help me in sorting this issue.
Thanks
Array of ObjIds should be defined this way in schema:
var EventsSchema = new mongoose.Schema({
root: {type: mongoose.Schema.Types.ObjectId, ref: 'root'},
voting: {type: [mongoose.Schema.Types.ObjectId], ref: 'Voting'}//**array bracers**
});
Also calling population over a field of type array like root field will return an empty array in the res of the API, see query hit by mongoose.set('debug', true); you will notice that mongoose is searching in event model not root.
though you have to tell mongoose in the population method which model to use in order to get the population working, unless you tell mongoose which model to search in .
populate({path:'vooting',model:'vooting'})

mongodb schema.createIndex is not a function

So I am trying to create an index in my messageSchema
var messageSchema = new Schema({
senderName : String,
content : String,
reply : String,
date: { type: Date, default: Date.now() },
room : { type: Schema.Types.ObjectId }
});
// this is how to tried to create the index
messageSchema.createIndex({content : "text"}, function(err, data){
console.log(err);
console.log(data);
});
//Also tried
messageSchema.createIndex({content : "text"});
//tried this too
messageSchema.createIndex({"content" : "text"});
The error I keep on getting is
TypeError: messageSchema.createIndex is not a function
Can anyone help me with this.
It seems you are using mongoose. Under the hood,
Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.
In the mongo shell, collection.createIndex() works, but in mongoose you need to use mySchema.index(). Mongoose will do the work.
See here for more information: http://mongoosejs.com/docs/guide.html.
from mongoose:
var messageSchema = new Schema({
senderName : String,
content : { type: String, index: true },
reply : String,
date: { type: Date, default: Date.now() },
room : { type: Schema.Types.ObjectId }
});
messageSchema.index({content: 'text'});
The method you are looking for is called index, not createIndex

associative array does not save mongoose

tournament.js
var mongoose = require('mongoose');
var TournamentPlayer = require('../models/tournamentPlayer');
var SportPlayer = require('../models/sportPlayer');
var Schema = mongoose.Schema;
var TournamentSchema = new Schema({
tournamentPlayers:[{
type: Schema.Types.Mixed,
ref: 'TournamentPlayer'
}],
buyin: Number,
entrants: Number,
prizePool: Number,
name: String,
sport: String,
endOfRegistration:Date,
sportsPlayers:[{
type: Schema.Types.Mixed,
ref: 'SportPlayer'
}],
created: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('Tournament', TournamentSchema);
api.js
tournament.tournamentPlayers[player.userId]=player;
console.log("ass array"+util.inspect(tournament.tournamentPlayers,false,null));
console.log("ass array element" + util.inspect(tournament.tournamentPlayers[player.userId] ,false,null));
console.log("ass array just in case"+util.inspect(tournament.tournamentPlayers,false,null));
tournament.tournamentPlayers.push(player);
console.log("push"+util.inspect(tournament.tournamentPlayers,false,null));
Output
ass array[]
ass array element{ username: 'batman',
roster:
{ __v: 0,
userId: '57bb89eb10c4b4ac124980b9',
tournamentId: '57d49f5169cc78ac21c5e791',
_id: '57d4b421315f1b501ad5456f',
playerRoster:
[ { _id: '57cfe922dcba0f295f57e26d', playerFirstName: 'Julio' },
{ _id: '57cfe939dcba0f295f57e274', playerFirstName: 'Odell' } ] },
rank: 'blah',
totalPoints: 0,
userId: '57bb89eb10c4b4ac124980b9',
_id: '57d4b421315f1b501ad54570' }
ass array just in case[]
push[{"username":"batman","roster":{"__v":0,"userId":"57bb89eb10c4b4ac124980b9","tournamentId":"57d49f5169cc78ac21c5e791","_id":"57d4b421315f1b501ad5456f","playerRoster":[{"_id":"57cfe922dcba0f295f57e26d","playerFirstName":"Julio"},{"_id":"57cfe939dcba0f295f57e274","playerFirstName":"Odell"}]},"rank":"blah","totalPoints":0,"userId":"57bb89eb10c4b4ac124980b9","_id":"57d4b421315f1b501ad54570"}]
I am trying to declare and add objects to an associative array. When I look them up, I want to use userId instead of _id. When trying with this code, the object can be called directly tournamentPlayers[userId], but doesn't display as part of the array tournamentPlayers. When I do a regular push, it displays, but this isn't what I want. I am able to use the object, but can't save it through mongoose.
I've seen a couple of questions but they did not answer this. The second answer here has strict: false as a setting, but not for a single schema element.
Mongoose: Saving as associative array of subdocuments vs array of subdocuments
How can I declare and add objects to an associative array in mongoose?

Mongoose: retrieving array of ObjectIds from collection

My database has following type of documents for Categories collection.
{
"_id" : ObjectId("56716afa403743492828aa07"),
"cat_name" : "watches",
"cat_parent_id" : [
ObjectId("56716afa403743492828aa01"),
ObjectId("56716afa403743492828aa03")
]
.........
}
I first created database with Robomongo, then I'm trying to fetch data using mongoose and created following Schema.
var categorySchema = new Schema({
'cat_name' : String,
'cat_parent_id' : [{ type : mongoose.Types.ObjectId }],
.......
});
but when I'm getting the result through following callback,
Categories.find(function(err,categories){........});
the cat_parent_id array is empty.
Edit:
When I replace mongoose.Types.ObjectId with Schema.Types.ObjectId or String,It works.Can anyone provide reason for that?
You need to add reference for the ObjectId type:
var categorySchema = new Schema({
'cat_name' : String,
'cat_parent_id' : [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Categories'
}],
.......
});

Unique and Sparse Schema-level Index MongoDB and Mongoose

I am trying to create an index on two fields of a schema that are to be unique and sparse in MongoDB using Mongoose as follows:
var ArraySchema = new Schema ({
user_id: {type: mongoose.Schema.Types.ObjectId, ref:'User'},
event_id: {type: mongoose.Schema.Types.ObjectId, ref:'Event'}
}, {_id:false});
ListSchema.index({user_id:1, event_id:1}, {sparse:true, unique:true});
Which is then used in an array in the User schema as such:
var User = new Schema({
arrayType1 : {
type: [ArraySchema]
},
arrayType2 : {
type: [ArraySchema]
},
arrayType3 : {
type: [ArraySchema]
}
//More specifications for user schema...
});
However, when trying to save multiple users without the array field, errors are thrown for duplicate fields. The error in Mocha looks similar to this: array.event_id_1 dup key {null, null}. An example of a segment of code that would throw this error is as follows:
var user1, user2;
user1 = new User({
username : 'username1',
password : 'password'
});
user2 = new User({
username : 'username2',
password : 'password'
});
user1.save(function() {
user2.save();
});
Here is my reasoning behind making the the fields of ArraySchema unique and sparse: If the array field is specifed, I do not want the array to contain duplicate objects; however, the array field is not required, so there will be many Users that have null for this field. Obviously I cannot use field-level indices since there are multiple fields that would need an index (arrayType1, arrayType2, arrayType3).
It appears that doing this sort of thing is not supported, at least at this time. The alternative would be to create a compound index on these fields then whenever adding a new element to the field use user.arrayType1.addToSet(). Here is an example of how this would work:
ArraySchema:
var ArraySchema = new Schema ({
user_id: {type: mongoose.Schema.Types.ObjectId, ref:'User'},
event_id: {type: mongoose.Schema.Types.ObjectId, ref:'Event'}
}, {_id:false});
ListSchema.index({user_id:1, event_id:1});
User schema:
var User = new Schema({
arrayType1 : {
type: [ArraySchema]
},
arrayType2 : {
type: [ArraySchema]
},
arrayType3 : {
type: [ArraySchema]
}
//More specifications for user schema...
});
Then I could declare new users as usual (as I did in the question); however, when I want to add a new element to arrayType1, for example, I would use the following line of code to add to new element only if it is not already there:
user.arrayType1.addToSet({user_id : user2._id, event_id : event._id});
user.save(function(err, result) {
//Callback logic.
};
Where user2 and event are defined earlier in the code and saved to the db. Alternatively I could use Mongoose's update function as such:
User.update({_id : user._id}, {
$addToSet : {
arrayType1 : {
user_id : user2._id,
event_id : event._id
}
}
}, function(err) {
//Callback logic.
}
);

Resources