I have a post call that inserts records in an Atlas mongodb database, the Atlas service has a trigger active to increment a correlative field (no_hc), then I make a query to retrieve that correlative field with the _id generated in the insert of the document. I put the code below so that they can tell me what I am doing wrong since this code sometimes returns null the field no_hc. Thanks since now
I add information about what I need to execute. I have a collection on which every time a document is added the mongodb server executes a trigger to increment a certain field, the problem is that the findoneandupsert query returns the inserted document with the autoincrement field set to null, since apparently the trigger is executed after the result of findoneandupsert is returned, how can I solve this issue?
router.post('/admisionUpsert', (req, res) => {
admisionUpsert(req.body)
.then(data => res.json(data))
.catch(err => res.status(400).json({ error: err + ' Unable to add ' }));
})
async function admisionUpsert(body) {
let nohc = body.no_hc
delete body['no_hc'];
let id;
let noprot
await Paciente.findOneAndUpdate(
{ no_hc: nohc },
{
apellido: body.apellido,
nombre: body.nombre,
sexo: body.sexo,
no_doc: body.no_doc,
fec_nac: body.fec_nac,
calle: body.calle,
no_tel: body.no_tel,
email: body.email
}, {
new: true,
upsert: true
}
)
.then(data => { id = data._id })
console.log("id pac", id)
Paciente.findOne({ _id: id }).then(data => { nohc = data.no_hc })
console.log("nohc pac", nohc)
await Protocolo.findOneAndUpdate(
{ no_prot: "" },
{
cod_os: body.cod_os,
no_os: body.no_os,
plan_os: body.plan_os,
no_hc: nohc,
sexo: body.sexo,
medico: body.medico,
diag: body.diag,
fec_prot: body.fec_prot,
medicacion: body.medicacion,
demora: body.demora
}, {
new: true,
upsert: true
}
)
.then(data => { id = data._id })
console.log("id prot", id)
Protocolo.findOne({ _id: id }).then(data => { noprot = data.no_prot })
console.log("noprot prot", noprot)
let practicasProtocolo = []
body.practicas_solicitadas.map((practica, index1) => {
practicasProtocolo.push({
no_prot: noprot,
cod_ana: practica.codigo,
cod_os: practica.cod_os,
estado_administrativo: practica.estado_administrtivo,
estado_muestra: practica.estado_muestra,
estado_proceso: practica.estado_proceso,
})
practica.parametro.map((parametro, index) => {
par = parametro.codigo
tipo_dato = parametro.tipo_dato
if ((tipo_dato === "numerico") || (tipo_dato === "frase") || (tipo_dato === "codigo")) {
practicasProtocolo[index1][par] = null;
}
})
})
console.log(practicasProtocolo)
practicasProtocolo.map(async (practica, index) => {
await new Practica(practica).save()
})
return { nohc: nohc, noprot: noprot }
}
Related
I'm executing an upsert mutation on MongoDB to create a new document or update an existing document. If the document exists, the mutation returns the id as expected. If a new document is created, the mutation returns null (in both Apollo sandbox and via console.log) in the initial return then in subsequent returns it will return the id. I need it to return the id of the newly created document immediately (on the first return) so I can use that id in subsequent actions.
Starting from the beginning here's the setup:
TYPEDEF
updateHourByEmployeeIdByJobDate(
jobDate: String
startTime: String
endTime: String
hoursWorked: String
employee: String
): Hour
RESOLVER
updateHourByEmployeeIdByJobDate: async (
parent,
{ jobDate, startTime, endTime, hoursWorked, employee },
context
) => {
// if (context.user) {
console.log("resolver hours update = ");
return Hour.findOneAndUpdate(
{ employee, jobDate },
{
jobDate,
startTime,
endTime,
hoursWorked,
employee,
},
{
upsert: true,
}
);
// }
// throw new AuthenticationError("You need to be logged in!");
},
MUTATION
//UPDATE HOUR RECORD - CREATES DOCUMENT IF IT DOESN'T EXIST OR UPDATES IF IT DOES EXIST VIA THE UPSERT OPTION ON THE RESOLVER
export const UPDATE_HOURS_BYEMPLOYEEID_BYJOBDATE = gql`
mutation UpdateHourByEmployeeIdByJobDate(
$jobDate: String
$startTime: String
$endTime: String
$hoursWorked: String
$employee: String
) {
updateHourByEmployeeIdByJobDate(
jobDate: $jobDate
startTime: $startTime
endTime: $endTime
hoursWorked: $hoursWorked
employee: $employee
) {
_id
}
}
`;
FRONT-END EXECUTION
const [ mostRecentHourUpdateId, setMostRecentHoursUpdateId ] = useState();
const [updateHours] = useMutation(UPDATE_HOURS_BYEMPLOYEEID_BYJOBDATE, {
onCompleted: (data) => {
console.log('mutation result #1 = ', data)
setMostRecentHoursUpdateId(data?.updateHourByEmployeeIdByJobDate?._id);
console.log('mutation result #2 = ', mostRecentHourUpdateId)
},
});
//section update database - this mutation is an upsert...it either updates or creates a record
const handleUpdateDatabase = async (data) => {
console.log(data);
try {
// eslint-disable-next-line
const { data2 } = await updateHours({
variables: {
jobDate: moment(data.date).format("MMMM DD YYYY"), //"January 20 2023"
startTime: `${data.startTime}:00 (MST)`, //"12:00:00 (MST)"
endTime: `${data.endTime}:00 (MST)`, //"13:00:00 (MST)"
hoursWorked: data.hours.toString(), //"3.0"
employee: userId, //"6398fb54494aa98f85992da3"
},
});
console.log('handle update database function = data = ', data2); //fix
} catch (err) {
console.error(err);
}
singleHoursRefetch();
};
I've tried using onComplete as part of the mutation request as well as useEffect not to mention running the mutation in Apollo Sandbox. Same result in all scenarios. The alternative is to re-run the useQuery to get the most recent / last record created but this seems like a challenging solution (if at some point the records are sorted differently) and/or seems like I should be able to get access to the newly created record immediately as part of the mutation results.
You'll want to use { returnNewDocument: true }
Like this:
const getData = async () => {
const returnedRecord = await Hour.findOneAndUpdate( { employee, jobDate }, { jobDate, startTime, endTime, hoursWorked, employee, }, { upsert: true, returnNewDocument: true } );
// do something with returnedRecord
}
getData();
For more information:
https://www.mongodb.com/docs/manual/reference/method/db.collection.findOneAndUpdate/
Basically what I want to do is that I have an ObjectId of a qr. I want to use that ObjectId to find out which qrBlock does it belong. Im leaving my dbmodel here
so you can track easily.
qrRoute.post("/scanQr", (req, res) => {
let { data } = req.body;
var id = mongoose.Types.ObjectId(data);
Qr.findById(id)
.exec()
.then((qrr) => {
QrBlock.find({ qr: { "qr.$": id } }, (qrblck) => {
console.log(qrblck);
});
});
});
I tried this code above it didn't work.
did you try this way
qrRoute.post("/scanQr", (req, res) => {
let { data } = req.body;
var id = mongoose.Types.ObjectId(data);
Qr.findById(id)
.exec()
.then((qrr) => {
QrBlock.find({ qr: id }, (qrblck) => {
console.log(qrblck);
});
});
});
QrBlock.findOne({ qr: { $all: [qrr._id] } })
this worked for me
I do query with logic "insert if not exists". Can i return upsert result without additional queries ?
var u = Builders<Blog>.Update
.SetOnInsert(f => f.BlogId, blogId)
.SetOnInsert(f => f.VideoId, videoId)
-- other fields...
var blog = Blog.FindOneAndUpdate<Blog>(c => c.BlogId == blogId && c.VideoId == VideoId, u,
new FindOneAndUpdateOptions<Blog>{IsUpsert = true, ReturnDocument = ReturnDocument.After}
);
bool wasUpsert = ?
return wasUpsert;
Use the new: true option, see 4.0 release notes.
Milestone.findOneAndUpdate({
......
}, {
......
}, {upsert: true, 'new': true}, function(err, res) {
// err === null
// res === null
done(err, res);
});
I would do it like this:
var filter = Builders<MyCollectionModel>.Filter
.Eq(x => x.Id, ObjectId.Parse("5ecd93f739a1c716ab2c2d44"));
var update = Builders<MyCollectionModel>.Update.Set(x => x.Email, "john.smith#gmail.com");
var updateResult = await context.MyCollectionModel
.UpdateOneAsync(filter, update, new UpdateOptions {IsUpsert = true});
updateResult.Dump(); // LINQPad
Then if a document with that id exists but no change was made you will get:
if a document with that id exists and the email was changed you will get:
and finally, if the document did not exist and therefore it was added, UpsertedId will show its id.
I'm having difficulty creating the routes to send to MongoDB.
When I return user, it returns the full database. This goes for using User or 'user'.
User is a model
let User = require('../models/user.model');
User.findById(req.params.id)
.then(user => {
if (!user)
res.status(404).send("data is not found");
else
for(var key in req.body.proposal) {
//res.send(user.proposal)
//res.send(user)
//res.send(User.username)
user.proposal.insertOne(
{
"uid" : req.body.proposal[key].uid,
"clientEmail" : req.body.proposal[key].clientEmail,
"summary" :req.body.proposal[key].summary,
"terms" :req.body.proposal[key].terms,
"form" :req.body.proposal[key].form
} //update
)
}
user.save()
.then(user => res.json(user))
.catch(err => res.status(400).json('Error: ' + err));
})
.catch(err => res.status(400).json('Error: ' + err));
});
Thank you in advanced!
It should be something like this :
let proposalArr = [];
for (const key in req.body.proposal) {
proposalArr.push({
uid: req.body.proposal[key].uid,
clientEmail: req.body.proposal[key].clientEmail,
summary: req.body.proposal[key].summary,
terms: req.body.proposal[key].terms,
form: req.body.proposal[key].form
});
}
user.proposal = proposalArr;
user.save().............
You can't use .insertOne on result of database query, it's a function of mongoose model to insert new document to collection but not to insert new fields to objects. You need to do just like adding new fields to json object using .js code, but mongoose will keep track of object's changes & when you use .save() it can update the document in collection with all those changes.
Instead of two DB calls, you can do that in one call, Check : .findByIdAndUpdate() & try below sample code :
let proposalArr = [];
for (const key in req.body.proposal) {
proposalArr.push({
uid: req.body.proposal[key].uid,
clientEmail: req.body.proposal[key].clientEmail,
summary: req.body.proposal[key].summary,
terms: req.body.proposal[key].terms,
form: req.body.proposal[key].form
});
}
User.findByIdAndUpdate(
req.params.id,
{
proposal: proposalArr
},
{ new: true }
)
.then(user => {
if (!user) res.status(404).send("data is not found");
res.json(user);
})
.catch(err => res.status(400).json("Error: " + err));
I am trying to use the Waterline .native() method to query an item by id in the database. This is what my code looks like:
// Consutruct the query based on type
var query = {};
if (req.param('type') === 'id') {
query = { _id: req.param('number') };
} else {
query = { 'data.confirmationNumber': req.param('number') };
}
Confirmations.native(function(error, collection) {
if (error) {
ResponseService.send(res, 'error', 500, 'Database error.');
} else {
collection.find(query).toArray(function(queryError, queryRecord) {
if (queryError) {
ResponseService.send(res, 'error', 500, 'Database error.');
} else {
if (queryRecord.length > 0) {
ResponseService.send(res, 'success', 200, queryRecord[0]);
} else {
ResponseService.send(res, 'error', 404, 'Your confirmation details could not be found.');
}
}
});
}
});
When the query is 'data.confirmationNumber' it works but if it is '_id' it dows not work. How do I fix this?
if your Id is a ObjectId see this
var ObjectId = require('mongodb').ObjectID;
{_id: new ObjectId(req.param('number') )}
Iniside Model and in attribute define the id field like this
id : {type : 'objectid',primaryKey:true}
When you are querying the code
Here my model name is - QuizModel and the id is coming in the params quizId so here quizId is equal to the _id in the mongodb database
QuizModel.find({_id: QuizModel.mongo.objectId(quizId)})
.then(function(response){
})
.catch(function(error){
});