How to update a nested data object in MongoDB? - node.js

I have a collection user_subscriptions like this:-
{
user : '362382jwie92012kk209',
plan : 'we2344r55jwie92vg56k209',
planContemporayDetail : {
planName : 'Test Name'
planPrice : 20,
planStartAt : 1729192839,
planEndAt : 1729232839,
planExpire : true,
stripeSubscriptionId : 'gwi289101023'
},
status : 'active',
canceledAt : null
}
I want to update planContemporayDetail.planEndAt, planContemporayDetail.planExpire, status and canceledAt based on the value of user, plan, planContemporayDetail.stripeSubscriptionId
Here is my nodeJS code:-
const userSubscriptionData = {
'$set' : {
planContemporayDetail.planEndAt : parseInt(parseInt(canceledAt) * 1000),
planContemporayDetail.planExpired : true
},
status : canceledAt,
canceledAt : parseInt(parseInt(canceledAt) * 1000)
};
const condition = {
user : userId,
plan : PlanId,
planContemporayDetail.stripeSubscriptionId : stripeSubscriptionId
}
let subscriptionUpdate = await UserSubscription.findOneAndUpdate(condition, userSubscriptionData);
But I am getting syntax error that 'invalid token at planContemporayDetail.planEndAt'
How to fix this?

Related

Build Mongo Query based on query parameters in url

I want to build a query as per the value available in the query parameters of the URL. The sample URL is :-
http://localhost:3000/api/user?page=&status=&search&role_id=
So when the status is available, the where clause related to it should work, the same for search and role_id.
I have tried to built a query where pagination part along with search parameter is working perfectly. But when I pass/set the keys of
query string, the query shows no results.
The query I have build so far is something like this:-
let {page, search, status, role_id} = req.query;
role_id = role_id ? role_id : null;
status = status ? status : null;
const currentPage = parseInt(page) || 1;
const perPage = recordsPerPage;
const userData = await User.find({
$and: [
{
$or : [
{username:{'$regex' : search, '$options' : 'i'}},
{email:{'$regex' : search, '$options' : 'i'}}
]
},
{
$or : [
{status : status}
]
},
{
$or : [
{role_id : role_id}
]
},
{
email: { $ne: 'xxxxx#gmail.com' }
}
]
})
.sort({_id : -1})
.populate('role_id')
.skip((currentPage - 1) * perPage).limit(perPage);
Instead of trying to rely on $or and $and in your query, you can just conditionally add fields to your query. A mongoose query is just passed an object and can be built outside the function call.
This way you won't have to worry about edge cases such as a user with status null being returned whenever you leave out the status field from your query.
let {page, search, status, role_id} = req.query;
role_id = role_id ? role_id : null;
status = status ? status : null;
const currentPage = parseInt(page) || 1;
const perPage = recordsPerPage;
const query ={
email: { $ne: 'xxxxx#gmail.com' }
}
if (status) {
query.status = status
}
if (role_id) {
query.role_id = role_id
}
if (search) {
query.username = {'$regex' : search, '$options' : 'i'}
delete query.email
query['$and'] = [
{ email: {'$regex' : search, '$options' : 'i'}},
{ email: { $ne: 'xxxxx#gmail.com' } }
]
}
const userData = await User.find(query)
.sort({_id : -1})
.populate('role_id')
.skip((currentPage - 1) * perPage).limit(perPage);
As an aside, I think a query with a $regex and a $ne on the same field (email in your example) may be very slow once executed on a large collection.

How to compare mongoDB ObjectIds & remove duplicates in an array of documents using node.js?

I have an array called "doc" which contains a list, in which some of them contains same ref object id, I have to remove that duplicate, but none of the code is working because I'm filtering according to ref object id, which is in the form of object. I have to access the id inside the object and filter it according to that object id. here userId is the referance object id.
Answer.find({'blockId': questId}, (err, doc) => {
if(doc!=null){
userId = 0;
userList = [];
userIdd = 0;
uslist = [];
for(var i = 0; i<doc.length; i++){
if(userId != doc[i].userId){
userIdList.push({'userId':doc[i].userId});
userId = doc[i].userId;
}
}
}else{
}
});
If you're getting doc[i].userId field values as ObjectId()'s from DB, then try this :
Answer.find({ 'blockId': questId }, (err, doc) => {
if (err) {
// return here itself
}
let userId = '';
let userIdList = [];
if (doc.length) {
for (var i = 0; i < doc.length; i++) {
/** Since we're using mongoose use `.toHexString()` to convert to string & compare,
if you're using mongoDB driver use `toString()` to convert to string */.
if (userId != (doc[i].userId).toHexString()) {
userIdList.push({ 'userId': doc[i].userId });
userId = (doc[i].userId).toHexString();
}
}
} else {
console.log('No matching answers found for blockId ::', questId)
}
})
Above code should work via Node.Js, just in case if your intention is all about just to get unique userId's try this as it helps to achieve things in DB itself in quick :
Answer.aggregate({$match : {"blockId" : 1}},
{$group : {_id : {blockId: '$blockId'},userIds: {$addToSet : '$userId'} }}).lean(true).exec((err, doc)=> {})
Collection Data :
/* 1 */
{
"_id" : ObjectId("5e103f0b400289966e01dc47"),
"blockId" : 1,
"userId" : ObjectId("5dfeac7b400289966e2042c7")
}
/* 2 */
{
"_id" : ObjectId("5e103f34400289966e01e1f9"),
"blockId" : 1,
"userId" : ObjectId("5dfeac7b400289966e2042c5")
}
/* 3 */
{
"_id" : ObjectId("5e103f4a400289966e01e56c"),
"blockId" : 1,
"userId" : ObjectId("5dfeac7b400289966e2042c7")
}
/* 4 */
{
"_id" : ObjectId("5e103f51400289966e01e678"),
"blockId" : 1,
"userId" : ObjectId("5dfeac7b400289966e2042c6")
}
/* 5 */
{
"_id" : ObjectId("5e103f57400289966e01e793"),
"blockId" : 1,
"userId" : ObjectId("5dfeac7b400289966e2042c1")
}
/* 6 */
{
"_id" : ObjectId("5e103f61400289966e01e92b"),
"blockId" : 2,
"userId" : ObjectId("5dfeac7b400289966e2042c9")
}
/* 7 */
{
"_id" : ObjectId("5e1040c3400289966e021168"),
"blockId" : 1,
"userId" : ObjectId("5dfeac7b400289966e2042c5")
}
Result :
/* 1 */
/** Duplicates removed */
{
"_id" : {
"blockId" : 1
},
"userIds" : [
ObjectId("5dfeac7b400289966e2042c1"),
ObjectId("5dfeac7b400289966e2042c6"),
ObjectId("5dfeac7b400289966e2042c5"),
ObjectId("5dfeac7b400289966e2042c7")
]
}
Or if you just wanted to use .find() & still do it in node.js, again if your operation is all about unique userId's, then at-least add projection to your code in order to retrieve only needed fields from DB :
Answer.find({ 'blockId': questId }, {_id :0, 'blockId':1, userId:1 }, (err, doc) => { })
I got a simple solution for this.
if 'doc' is the array which contains duplicates.
userIdList = [];
userIdList = Object.values(doc.reduce((acc,cur)=>Object.assign(acc,{[cur.userId.toString()]:cur}),{}));

Making third collection out of two collections and want all of fields in the third collections in MONGODB

var mapDevice = function(){
var values = {
Device_Id: this.Device_Id,
Module_Id : this.Module_Id,
Area_Id: this.Area_Id,
Gas_Id: db.Reading.findOne({Gas_Id: db.Reading.Gas_Id})
};
emit(this.Device_Id, values);
};
var mapReading = function(){
var values = {
Device_Id :this.Device_Id,
Gas_Id :this.Gas_Id
Module_Id: db.Device.findOne({Module_Id: db.Device.Module_Id}),
Area_Id: db.Device.findOne({Area_Id: db.Device.Area_Id})
};
emit(this.Device_Id, values);
};
var reduce = function(key, values){
var outs ={
Device_Id: null,
Module_Id : null,
Area_Id: null,
Gas_Id: null
};
values.forEach(function(v){
if(outs.Device_Id ==null){
outs.Device_Id = v.Device_Id
}
if(outs.Module_Id ==null){
outs.Module_Id = v.Module_Id
}
if(outs.Area_Id==null){
outs.Area_Id = v.Area_Id
}
if(outs.Gas_Id==null){
outs.Gas_Id = v.Gas_Id
}
});
return outs;
};
db.Reading.mapReduce(mapReading,reduce,{
out: { merge: "map_reduce_example" },
query: { 'Concentration':{ $gt: 3 }}
});
db.Device.mapReduce(mapDevice,reduce,{
out: { merge: "map_reduce_example" }
});
///////// DEVICE COLLECTION
{
"_id" : ObjectId("5a89cb9b7c417b7a8fc07a91"),
"Device_Id" : "DEEV2",
"Module_Id" : "MOD1",
"Area_Id" : "SUM"
}
//////////READING COLLECTION
{
"_id" : ObjectId("5a893d946fa0c25613c14427"),
"device_id" : "DEEV1",
"Gas_Id" : "CO2",
"Concentration" : 401
}
/////////MAP_REDUCE_EXAMPLE COLLECTION
{
"_id" : null,
"value" : {
"Device_Id" : null,
"Module_Id" : undefined,
"Area_Id" : undefined,
"Gas_Id" : "CO2"
}
}
Been trying to merge 2 collections and make 3rd out of it using MAPREDUCE in mongodb. Want field included in the third(new) collection not only common ones but all of them. My two collections are DEVICE and READING and I want to have the collection map_reduce_example collection(which i am getting null values).
Following are the supporting screenshots to my code:
[![This is ss of my "**Reading**" collection][1]][1]
[![This is ss of my "**Device**" collection][2]][2]
[![This is how i want my final collection to be i.e **"map_reduce_example"** collection to be][3]][3]
[1]: https://i.stack.imgur.com/qNkNR.png
[2]: https://i.stack.imgur.com/v6sFK.png
[3]: https://i.stack.imgur.com/AzTqO.png

Maximum call stack exceeded mongoose

I'm trying to save documents into a mongodb collection using mongoose/node.js with the schema ,
var userSchema = {
userName : String,
userId : Number,
Location : [{Country : String}]
};
var mySchema = {
userData : userSchema,
title : String
};
var MyModel = mongoose.model('MyModel' , mySchema);
However on ,
req.MY_user = JSON.parse(res.body); // Response from an API
MyModel.update({title : 'sometitle'} , {userData : req.MY_user , title : 'sometitle'} ,
{upsert : true} ,
function(err , raw){ ... });
I get an error, Maximum call stack exceeded.
Strangely, it works fine on my local machine running Mac.
Problem arises when deployed to linux/windows.
Any solutions please ?
Eg Response :
req.MY_user = {
userName : 'John',
userId : 12345,
Location : [{Country : 'Rus'} , {Country : 'Ind'}]};
Update , adding error.stack,
Range Error : at Function.isArray (native),
at shouldFlatten node_modules/mongoose/lib/services/common.js 81:13
at modifiedPaths node_modules/mongoose/lib/services/common.js 65:7
(above line is repeated multiple times)

NetSuite SuiteTalk 2.0 address sublist defaultshipping and defaultbilling not being set

I am having a heck of a time getting the defaultshipping and defaultbilling checks to be set when inserting a new customer record. I have included my code below and have tried several different things but for some reason on the first address that is inserted both defaultshipping and defaultbilling are set but the second address has nothing checked.
define([ 'N/record', 'N/runtime' ],
function(record, runtime) {
function doPost(requestBody) {
var custRec = record.create({
type : record.Type.CUSTOMER,
isDynamic : true
});
var addresses = [
custBillAddr = {
addr1 : '2100 S. Blah St.',
addr2 : '',
addressee : 'Test Person',
city : 'Test Ville',
defaultbilling : true,
defaultshipping : false,
state : 'IA',
zip : '12345'
}, custShipAddr = {
addr1 : '5144 S. Test St.',
addr2 : '',
addressee : 'Tester Test',
city : 'Test City',
defaultbilling : false,
defaultshipping : true,
state : 'TX',
zip : '54321'
}];
var curScript = runtime.getCurrentScript();
var defEntity = curScript.getParameter({
name : 'custscript_default_entity_status'
});
var defSub = curScript.getParameter({
name : 'custscript_default_subsidary'
});
var custData = {
accountnumber : '112233',
companyname : 'Testing Company',
email : 'Testing#example.com',
entityid : '112233',
entitystatus : defEntity,
externalid : '123',
subsidiary : defSub,
};
for ( var key in custData) {
if (custData.hasOwnProperty(key)) {
custRec.setValue({
fieldId : key,
value : custData[key]
});
}
}
/* create address sub lists here */
custRec = upsertAddresses(custRec, addresses);
var recordId = custRec.save({
enableSourcing : false,
ignoreMandatoryFields : false
});
return JSON.stringify(recordId);
}
function upsertAddresses(custRec, addresses) {
for ( var address in addresses) {
custRec.selectNewLine({ sublistId : 'addressbook' });
var addList = custRec.getCurrentSublistSubrecord({ sublistId : 'addressbook', fieldId : 'addressbookaddress' });
for ( var key in addresses[address]) {
addList.setValue({ fieldId : key, value : addresses[address][key] });
}
custRec.commitLine({ sublistId : 'addressbook' });
}
return custRec;
}
return {
post : doPost,
};
});
In the addresses array of address objects I tried using:
defaultbilling : true
defaultbilling : 'T'
defaultbilling : 'Yes'
defaultbilling : 1
but none of them worked to set the field and I am not getting an error. Hoping someone here can tell me what I did wrong when trying to set those fields.
I had a very similar issue. Turns out that the addressbook in 2.0 needs a subrecord of the sublist. The code below is not exactly what you are asking for, but it should help you with what you need to do. In mine I'm getting the values, where you just need to set them. Hope this helps out.
define(['N/record','N/https','N/search'],function(record,https,search){
function sendContactData(context){
var contactNewRecord=context.newRecord;
if(context.type=='create' || contactNewRecord.getValue('nluser')=='1234'){return;}
var contactID=contactNewRecord.getValue('id');
var contactObjectRecord=record.load({type:record.Type.CONTACT,id:contactID,isDynamic:true,});
var shippingAddr1='';
var shippingCity='';
var shippingState='';
var shippingZip='';
var shippingCountry='';
var numLines=contactNewRecord.getLineCount({sublistId:'addressbook'});
if(numLines>0){
for(var addressCount=0;addressCount<numLines;addressCount++){
var addressShipping=contactNewRecord.getSublistValue({
sublistId:'addressbook',
fieldId:'defaultshipping',
line:addressCount
});
if(addressShipping==true){break;}
}
}
if(addressShipping==true){
//Select the line set as the default shipping:
contactObjectRecord.selectLine({sublistId:"addressbook",line:addressCount});
var shippingAddressSubrecord=contactObjectRecord.getCurrentSublistSubrecord({sublistId:"addressbook",fieldId:"addressbookaddress"}); //Access the addressbookaddress subrecord:
if(shippingAddressSubrecord){
shippingAddr1=shippingAddressSubrecord.getValue({fieldId:'addr1'});
shippingCity=shippingAddressSubrecord.getValue({fieldId:'city'});
shippingState=shippingAddressSubrecord.getValue({fieldId:'state'});
shippingZip=shippingAddressSubrecord.getValue({fieldId:'zip'});
shippingCountry=shippingAddressSubrecord.getValue({fieldId:'country'});
}
}
}; /* END sendContactData() */
return{
afterSubmit:sendContactData
} /* END return block */
}); /* END define(['N/record'],function(record) */

Resources