duplicate ID mongodb - node.js

coordinatesCollection.findOne({
"unique_id": unique_id,
}, function(err, object) {
if (object) {
coordinatesCollection.update({
"unique_id": unique_id
}, {
$push: {
coordinates: {
"coordinateX": msg.coordinatex,
"coordinateY": msg.coordinatey,
"ms_time": ms_time,
"page": msg.page,
}
}
})
} else {
coordinatesCollection.insert({
"unique_id": unique_id,
"coordinates": [{
"coordinateX": msg.coordinatex,
"coordinateY": msg.coordinatey,
"ms_time": ms_time,
"page": msg.page,
}]
})
}
});
});
The objective of this code is: If unique_id exists add coordinateX, coordinateY, ms_time and page to coordinates arrays if not exists insert unique_id and new array to coordinates.
When I saw the collection I found multiple documents with the same unique_id.
What is wrong ?

For this problem I suggest You to use instead only update function with $exists statement in query.

Related

Update nested object in array MongoDB

I need to find and update documents with category that corresponding to the query. Array could contain mo than one corresponding id.
Query:
{
"ids": ["61f1cda47018c60012b3dd01", "61f1cdb87018c60012b3dd07"],
"userId": "61eab3e57018c60012b3db3f"
}
I got collection with documents like:
`{
"_id":{"$oid":"61f1cdd07018c60012b3dd09"},
"expenses":[
{"category":"61eafc104b88e154caa58616","price":"1111.00"},
{"category":"61f1cdb87018c60012b3dd07","price":"2222.00"},
{"category":"61f1cda47018c60012b3dd01","price":"1241.00"},
{"category":"61f1cdb87018c60012b3dd07","price":"111.00"}
],
"userId":"61eab3e57018c60012b3db3f"
}`
my method:
async myMethod(ids: [string], userId: string) {
try {
const { ok } = await this.ExpensesModel.updateMany(
{"userId": userId, "expenses.category": { $in: ids }},
{$set: {"expenses.$.category": "newCategoryID"}}
);
return ok
} ........
I path array of ids ["61f1cda47018c60012b3dd01","61f1cdb87018c60012b3dd07","61f1cdb87018c60012b3dd07"] and userId, this code update only 1 category by document.
So can i made it with mongo build in methods? or i need to find matching document and update it it by my self and after that update or insert;
Update with arrayFilters
db.collection.update({
"expenses.category": {
$in: [
"61f1cda47018c60012b3dd01",
"61f1cdb87018c60012b3dd07"
]
}
},
{
$set: {
"expenses.$[elem].category": "61eab3e57018c60012b3db3f"
}
},
{
arrayFilters: [
{
"elem.category": {
$in: [
"61f1cda47018c60012b3dd01",
"61f1cdb87018c60012b3dd07"
]
}
}
]
})
mongoplayground

MongoDB request: Filter only specific field from embedded documents in embedded array

I have got some troubles with a MongoDB request that I would like to execute. I am using MongoDB 3.2 with Mongoose in a node.js context. Here is the document:
{
_id: ObjectId('12345'),
name: "The name",
components: [
{
name: "Component 1",
description: "The description",
container: {
parameters: [
{
name: "Parameter 1",
value: "1"
},
// other parameters
],
// other information...
}
},
// other components
]
}
And I would like to list all the parameters name for a specific component (using component name) in the specific document (using _id) with this output:
['Parameter 1', 'Parameter 2', ...]
I have got a mongoose Schema to handle the find or distinct methods in my application. I tried many operations using $ positioning operator. Here is my attempt but return all parameters form all components:
listParameters(req, res) {
DocumentModel.distinct(
"components.container.parameters.name",
{_id: req.params.modelId, "components.name": req.params.compId},
(err, doc) => {
if (err) {
return res.status(500).send(err);
}
res.status(200).json(doc);
}
);
}
but the output is the list of parameter name but without the filter of the specific component. Can you help me to find the right request? (if possible in mongoose JS but if it is a Mongo command line, it will be very good :))
You would need to run an aggregation pipeline that uses the $arrayElemAt and $filter operators to get the desired result.
The $filter operator will filter the components array to return the element satisfying the given condition whilst the $arrayElemAt returns the document from the array at a given index position. With that document you can then project the nested parameters array elements to another array.
Combining the above you ideally want to have the following aggregate operation:
DocumentModel.aggregate([
{ "$match": { "_id": mongoose.Types.ObjectId(req.params.modelId) } },
{ "$project": {
"component": {
"$arrayElemAt": [
{
"$filter": {
"input": "$components",
"as": "el",
"cond": { "$eq": ["$$el.name", req.params.compId] }
}
}, 0
]
}
} },
{ "$project": {
"parameters": "$component.container.parameters.name"
} }
], (err, doc) => {
if (err) {
return res.status(500).send(err);
}
const result = doc.length >= 1 ? doc[0].parameters : [];
res.status(200).json(result);
})
i don`t know how to do it with mongoose but this will work for you with mongo
db.getCollection('your collaction').aggregate([ // change to youe collaction
{$match: {_id: ObjectId("5a97ff4cf832104b76d29af7")}}, //change to you id
{$unwind: '$components'},
{$match: {'components.name': 'Component 1'}}, // change to the name you want
{$unwind: '$components.container.parameters'},
{
$group: {
_id: '$_id',
params: {$push: '$components.container.parameters.name'}
}
}
]);

How to update a array value in Mongoose

I want to update a array value but i am not sure about the proper method to do it ,so for i tried following method but didnt worked for me.
My model,
The children field in my model
childrens: {
type: Array,
default: ''
}
My query,
Employeehierarchy.update({ _id: employeeparent._id} ,{ $set: {"$push": { "childrens": employee._id }} })
.exec(function (err, managerparent) {});
Can anyone please provide me help.Thanks.
You can't use both $set and $push in the same update expression as nested operators.
The correct syntax for using the update operators follows:
{
<operator1>: { <field1>: <value1>, ... },
<operator2>: { <field2>: <value2>, ... },
...
}
where <operator1>, <operator2> can be from any of the update operators list specified here.
For adding a new element to the array, a single $push operator will suffice e.g. you can use the findByIdAndUpdate update method to return the modified document as
Employeehierarchy.findByIdAndUpdate(employeeparent._id,
{ "$push": { "childrens": employee._id } },
{ "new": true, "upsert": true },
function (err, managerparent) {
if (err) throw err;
console.log(managerparent);
}
);
Using your original update() method, the syntax is
Employeehierarchy.update(
{ "_id": employeeparent._id},
{ "$push": { "childrens": employee._id } },
function (err, raw) {
if (err) return handleError(err);
console.log('The raw response from Mongo was ', raw);
}
);
in which the callback function receives the arguments (err, raw) where
err is the error if any occurred
raw is the full response from Mongo
Since you want to check the modified document, I'd suggest you use the findByIdAndUpdate function since the update() method won't give you the modified document, just the full write result from mongo.
If you want to update a field in the document and add an element to an array at the same time then you can do
Employeehierarchy.findByIdAndUpdate(employeeparent._id,
{
"$set": { "name": "foo" },
"$push": { "childrens": employee._id }
}
{ "new": true, "upsert": true },
function (err, managerparent) {
if (err) throw err;
console.log(managerparent);
}
);
The above will update the name field to "foo" and add the employee id to the childrens array.
can follow this
if childrens contains string values then model can be like:
childrens: [{
type : String
}]
if childrens contains ObjectId values of another collection _id and want populate then model can be like:
childrens: [{
type : mongoose.Schema.Types.ObjectId,
ref: 'refModelName'
}]
no need to use $set just use $push to insert value in childrens array. so query can be like:
Employeehierarchy.update(
{ _id: employeeparent._id},
{"$push": { "childrens": employee._id } }
).exec(function (err, managerparent) {
//
});
This will help I guess
Employeehierarchy.findOneAndUpdate(
{ _id:employeeparent._id },
{ $set: { "childrens": employee._id }}
)

Trying to find record using $in in mongoose

I'm trying to find record using $in in mongoose. But it's not working for me. I have same query in mongo shell its working but in mongoose it is not workinh
my schema
{
"_id": "574f1f979f44e7531786c80f",
"name": "mySchool2",
"branch": "karachi",
"location": "Clifton ",
"block": false,
"created_at": 1464803223441,
"updated_at": 1464803223441,
"__v": 0,
"classes": [
"574f216afd487958cd69772a"
],
"admin": [
"574f20509f44e7531786c811",
"57508a2a3a0a919c16ace3c0"
],
"teacher": [
"574f20f39f44e7531786c812",
"575002b48188a3f821c2a66e",
"57500bbaea09bc400d047bf6"
],
"student": [
"574f2d56590529c01a2a473b",
"574f2e5842c5885b1b1729ab",
"574f2ed542c5885b1b1729ae",
"574f2f57555210991bf66e07",
"574f2fcd087809b11bd8d5e4",
"574f301d1f5025d61b7392b6",
"574f30481d02afff1bb00c71",
"574f30b01d02afff1bb00c74",
"574f310038136b3d1cf31b96"
]
}
My mongose query
app.services._chkAdminSchool = function(payload){
var deferred = q.defer();
School
//.find({ teacher:{$in:['574f20f39f44e7531786c812']}})
.find({_id : "574f1f979f44e7531786c80f",admin:{"$in":[Object("57508a2a3a0a919c16ace3c0")]}})
//.select(filers)
.exec(function(error, record) {
if (error) {
deferred.reject({
status:404,
message: 'Error in API',
error: error
});
} else {
if(record.length === 0){
deferred.reject({
message: 'Admin and school doesnot match',
data: record
});
}else{
deferred.resolve({
message: 'Successfully get Admin',
data: record
});
}
}
});
return deferred.promise;
}
records are return empty array.
Thanks in advance for help
The query you use works fine for me and returns object, make sure you define admin field in Schema like this:
"admin": [{type: mongoose.Schema.ObjectId }]
to avoid admin array object being string. If you compare Object("57508a2a3a0a919c16ace3c0") to "57508a2a3a0a919c16ace3c0" it will return empty array, check and replay to me, thanks.
I am not sure about how you define your School Schema, but if you are saving id in admin array as String, you don't need to change to Object in your mongoose query.
School.find({
_id: "574f1f979f44e7531786c80f",
admin: {
$in : ['57508a2a3a0a919c16ace3c0']
}
}, functin (err, record) {
...
})

create a new object Id in mongoDB using node js

I am using the below code to insert data to mongodb
router.post('/NewStory', function (req, res) {
var currentObject = { user: userId , story : story , _id:new ObjectID().toHexString() };
req.db.get('clnTemple').findAndModify({
query: { _id: req.body.postId },
update: { $addToSet: { Stories: currentObject } },
upsert: true
});
});
This code is working fine if i remove the _id:new ObjectID().toHexString()
What i want to achieve here is that for every new story i want a unique _id object to be attached to it
What am i doing wrong?
{
"_id": {
"$oid": "55ae24016fb73f6ac7c2d640"
},
"Name": "some name",
...... some other details
"Stories": [
{
"userId": "105304831528398207103",
"story": "some story"
},
{
"userId": "105304831528398207103",
"story": "some story"
}
]
}
This is the document model, the _id that i am trying to create is for the stories
You should not be calling .toHexString() on this as you would be getting a "string" and not an ObjectID. A string takes more space than the bytes of an ObjectId.
var async = require('async'),
mongo = require('mongodb'),
db = require('monk')('localhost/test'),
ObjectID = mongo.ObjectID;
var coll = db.get('junk');
var obj = { "_id": new ObjectID(), "name": "Bill" };
coll.findAndModify(
{ "_id": new ObjectID() },
{ "$addToSet": { "stories": obj } },
{
"upsert": true,
"new": true
},
function(err,doc) {
if (err) throw err;
console.log(doc);
}
)
So that works perfectly for me. Noting the "new" option there as well so the modified document is returned, rather than the original form of the document which is the default.
{ _id: 55c04b5b52d0ec940694f819,
stories: [ { _id: 55c04b5b52d0ec940694f818, name: 'Bill' } ] }
There is however a catch here, and that is that if you are using $addToSet and generating a new ObjectId for every item, then that new ObjectId makes everything "unique". So you would keep adding things into the "set". This may as well be $push if that is what you want to do.
So if userId and story in combination already make this "unique", then do this way instead:
coll.findAndModify(
{
"_id": docId,
"stories": {
"$not": { "$elemMatch": { "userId": userId, "story": story } }
}
},
{ "$push": {
"stories": {
"userId": userId, "story": story, "_id": new ObjectID()
}
}},
{
"new": true
},
function(err,doc) {
if (err) throw err;
console.log(doc);
}
)
So test for the presence of the unique elements in the array, and where they do not exist then append them to the array. Also noting there that you cannot do an "inequality match" on the array element while mixing with "upserts". Your test to "upsert" the document should be on the primary "_id" value only. Managing array entries and document "upserts" need to be in separate update operations. Do not try an mix the two, otherwise you will end up creating new documents when you did not intend to.
By the way, you can generate an ObjectID just using monk.
var db = monk(credentials.database);
var ObjectID = db.helper.id.ObjectID
console.log(ObjectID()) // generates an ObjectID

Resources