Why new documents in mongo have an object and not an ObjectId? - javascript

When inserting new documents in mongodb, ids don't look like ObjectId and instead they look like an object.
"_id" : {
"_bsontype" : "ObjectID",
"id" : "U\u0013[-Ф~\u001d$©t",
"generationTime" : 1.43439e+09
}
Expected type:
"_id" : ObjectId("55107edd8e21f20000fd79a6")
My mongodb version is 3.0.3 and this is pretty much the code and the schema
var Script = {
run: function() {
return CourseModel.findQ()
.then(function(courses){
return courses.map(worker);
}).catch(function(error){
console.log(error);
});
}
};
function worker(course){
var category = { name: course.name, displayOrder: 0 };
return CategoryModel.createQ(category).then(function() {
course.set('name', undefined);
return course.saveQ();
});
}
module.exports = Script;
var CategorySchema = new Schema({
name: {
type: String,
required: true,
unique: true
},
active: {
type: Boolean,
default: true
},
displayOrder: Number,
updateDate: Date,
subcategories: [{
type: Schema.Types.ObjectId,
ref: 'subcategories'
}]
});

That is what an ObjectID is. It is simply an object that contains those properties.
http://docs.mongodb.org/manual/reference/object-id/
ObjectId is a 12-byte BSON type, constructed using:
a 4-byte value representing the seconds since the Unix epoch,
a 3-byte machine identifier,
a 2-byte process id, and
a 3-byte counter, starting with a random value.
{
"_bsontype" : "ObjectID",
"id" : "U\u0013[-Ф~\u001d$©t",
"generationTime" : 1.43439e+09
}
U\u0013[-Ф~\u001d$©t is the 12 character binary string which gets converted to the familiar 24 char hex string (55107edd8e21f20000fd79a6) when the object as a whole is represented as a text value (i.e. its .toString function is invoked)
In Mongoose the documents also have a .id getter which give you the 24 char hex as a string value.

The malformed ObjectIds are caused by a conflict with the mongoose version that mongoose-q is using. You'll need to update to mongoose-q to version 0.1.0. I was using 0.0.17 previously and saw exactly the same behavior that you saw here.

I was having the same issue here: ObjectID not storing hexadecimal value
It's definitely an issue with environments and something strange with the brew installation of MongoDB. I found that uninstalling from brew and reinstalling manually solved my issue. http://docs.mongodb.org/manual/tutorial/install-mongodb-on-os-x/
While I didn't figure out from a code/technical standpoint why it is returning the 12-byt BSON ObjectID rather than the Hexadecimal ObjectID... uninstalling MongoDB from brew and reinstalling it manually solved the issue.

Related

Mongoose - Deleting documents is unresponsive

I'm trying to use Mongoose (MongoDB JS library) to create a basic database, but I can't figure out how to delete the documents / items, I'm not sure what the technical term for them is.
Everything seems to work fine, when I use Item.findById(result[i].id), it returns a valid id of the item, but when I use Item.findByIdAndDelete(result[i].id), the function doesn't seem to start at all.
This is a snippet the code that I have: (Sorry in advance for bad indentation)
const testSchema = new schema({
item: {
type: String,
required: true
},
detail: {
type: String,
required: true
},
quantity: {
type: String,
required: true
}
})
const Item = mongoose.model("testitems", testSchema)
Item.find()
.then((result) => {
for (i in result) {
Item.findByIdAndDelete(result[i].id), function(err, result) {
if (err) {
console.log(err)
}
else {
console.log("Deleted " + result)
}
}
}
mongoose.connection.close()
})
.catch((err) => {
console.log(err)
})
I'm not sure what I'm doing wrong, and I haven't been able to find anything on the internet.
Any help is appreciated, thanks.
_id is a special field on MongoDB documents that by default is the type ObjectId. Mongoose creates this field for you automatically. So a sample document in your testitems collection might look like:
{
_id: ObjectId("..."),
item: "xxx",
detail: "yyy",
quantity: "zzz"
}
However, you retrieve this value with id. The reason you get a value back even though the field is called _id is because Mongoose creates a virtual getter for id:
Mongoose assigns each of your schemas an id virtual getter by default which returns the document's _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it by passing this option at schema construction time.
The key takeaway is that when you get this value with id it is a string, not an ObjectId. Because the types don't match, MongoDB will not delete anything.
To make sure the values and types match, you should use result[i]._id.

Mongoose findOne sending null

I am trying to edit a discord bot made in python (I stored data initially in python) and transferring it to javascript (node.js) and can't feature out while connecting to my old db why findOne giving me null while providing proper discord id.
Without anything inside
Code
anifarm.findOne();
Output
{
_id: 707876147324518400,
farmed: 17,
ordered: 5,
pimage: 'https://media.tenor.com/images/e830217a5d9926788ef25119955edc7f/tenor.gif',
pstatus: 'I want you to be happy. I want you to laugh a lot. I don’t know what exactly I’ll be able to do for you, but I’ll always be by your side.',
avg: 184,
speed: 2,
badges: [
'https://cdn.discordapp.com/attachments/856137319149207563/856137435696332800/Black-and-Yellow-Gaming-Badge--unscreen.gif',
'https://cdn.discordapp.com/attachments/856137319149207563/862219383866523688/Front-removebg-preview.png', 'https://cdn.discordapp.com/attachments/856137319149207563/862240758768599100/download-removebg-preview.png'
],
setBadges: 'https://cdn.discordapp.com/attachments/856137319149207563/862240758768599100/download-removebg-preview.png'
}
With id inside
Code
anifarm.findOne({
_id: 707876147324518400
});
Output
null
anifarm in the schema.
Decleared Schema
module.exports = mongoose.model('anifarm', new mongoose.Schema({
_id: Number,
farmed: {
type: Number,
default: 0
},
ordered: {
type: Number,
default: 0
},
pimage: {
type: String,
default: ""
},
pstatus: {
type: String,
default: ""
},
avg: {
type: Number,
default: 200
},
speed: {
type: Number,
default: 2
},
badges: {
type: Array,
default: []
},
setBadges: {
type: String,
default: ""
}
},
{
collection: 'anifarm',
versionKey: false
})
);
I cannot figure out what am I doing wrong. This problem also happens with .find()
Nothing inside find fetches everything by if I provide id it sends a empty array.
A Little help would be appreciated
For you problem use mongoose-long that should fix your problem.
This library will handle all long type data for mongoose since mongoose cannot handle long type data
you can't pass an id as a number, you will have to use ObjectId to convert the id to an instanceof ObjectId
Change your code like this
anifarm.findOne({
_id: mongoose.Types.ObjectId(707876147324518400);
});
If you're querying by _id, use findById() instead.
anifarm.findById("707876147324518400")
Official docs here

Mongoose: value not incrementing through $inc

I have been struggling with this issue for days. For some unknown reason, a specific field ("reviewCounts") is not incrementing no matter what alternative methods I try.
Here is my Schema
let itemSchema = new mongoose.Schema({
rank: Number,
image: String,
name: String,
title: String,
count: Number,
category: String,
ratings: Object,
reviewCounts: Number,
reviews: Array,
tags: Object,
})
and this is the update method:
Item.findOneAndUpdate({name: item,title:title}, {
$inc:{"reviewCounts":1},
$set:averageQuery,
$inc:query
},{strict:false},
function (err, data) {
}
}
$inc works completely find on "query" not it does not increment "reviewCounts". I have tried using $set to manually set the value, but that did not work too. I doubled-checked and confirmed that the field is int32 as intended. What could be the reason behind this issue?
When you build your update statement this way:
{
$inc:{"reviewCounts":1},
$set:averageQuery,
$inc:query
}
you're duplicating the $inc key in your JavaScript object. JavaScript interprets such code as:
{
$set:averageQuery,
$inc:query
}
so simply last usage of particular key "wins" thus you loose the reviewCounts part.
You need to make sure that there's only one $inc and you can use the spread operator to combine your $inc's:
$inc:{ ...query, "reviewCounts":1 }

Mongoose doesn't create TTL indexes

This is my Mongoose model:
var sessionSchema = new Schema({
_id: { type: String, required: true, index: { unique: true } },
user: { type: Schema.Types.ObjectId },
expire: { type: Date, index: { expireAfterSeconds: 21600 } }
})
module.exports = mongoose.model('Session', sessionSchema)
I need to be able to set a date object into expire (usually it's something like Date.now plus a few minutes) and have the object removed from the collection after 6 hours past the expiration.
However, I'm not able to have Mongoose to create the index. When I run db.sessions.getIndexes() in the mongo console, here's the output:
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "dev.sessions"
}
]
I've tried also with different syntaxes, like
expire: { type: Date, expires: 21600 } (Mongoose's short-hand version).
I tried also defining the index at the schema level:
sessionSchema.index({ expire: 1 }, { expireAfterSeconds: 21600 })
None is working.
Unlike others who asked questions on SO, my index is simply not created. I've tried also removing the collection and the database as well, and when they're recreated they still don't contain the index.
Versions: Mongoose 3.8.19, MongoDB 2.6.5 (OSX) and Node.js 0.10.33
Edit
More info: I tried creating the index directly from the mongo console, with:
db.sessions.ensureIndex({"expire":1}, {expireAfterSeconds: 21600})
That appears to be working (the index is created).
However, it's not working with Mongoose in any way.
Apparently the problem was that I created an index on the custom _id field. MongoDB creates an index on that field by itself, so when Mongoose was calling ensureIndex to create also the TTL index, it failed for both.
See https://github.com/LearnBoost/mongoose/issues/2459

Mongoose getter is getting undefined parameter

I'm storing a price value in my Mongoose schema according to the answer from how should i store a price in mongoose?
I have the following code in my schema definition:
price: {
value: {
type: Number,
get: getPrice,
set: setPrice,
min: 0
},
currency: {
type: String,
default: 'PLN',
trim: true,
enum: ['PLN', 'EUR']
}
},
and my get function:
function getPrice(num){
return (num/100).toFixed(2);
}
However, whenever this getter function is called I can see that the num parameter in undefined.
Do you know what might be the reason for that? And how could I fix this?
Add a default of zero for value. Also, mongoose is notoriously bad about subdocuments that are not inside an array, which may be causing this problem.
value: {
type: Number,
get: getPrice,
set: setPrice,
min: 0,
default: 0
},
If getter/setters give you problems with mongoose models, use the native static methods in mongoose schemas:
mySchema.static('getPrice', function(){
//'this' in the context means a document that shares the schema
return (this.price.value/100).toString(2);
});
You can invoke the method in any document that have said schema:
var myPrice = oneMongooseDocument.getPrice();
Is a very clean approach.

Categories