MogoDB findAndModify return WriteResult - mongodb

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.

Related

MongoDB and triggers

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 }
}

Mongoose query - how to create an object for every dataset that is returned

I'm query the database and returning an array of objects, which I then want to create an objet for each set of data based on new object properties as well as push each new object into an array. I believe I'm having problems with the promise not resolved, but can't figure out how to resolve it.
The data from the query returns fine, but its when it enter the for-loop, the object isn't created. It goes into the catch statement.
const express = require('express');
const router = express.Router();
const userTxModel = require('../models/userTx.model');
var RecurringTxObj = (name, user_id, next_amt, next_date, transactions) => {
this.name = name;
this.user_id = user_id;
this.next_amt = next_amt;
this.next_date = next_date;
this.transactions = [];
};
router.get('/getRecurringTx', (req, res) => {
const recurringTxArr = [];
userTxModel
.find({ recurring: true })
.exec()
.then((recurringTxData) => {
for (let data of recurringTxData) {
recurringTxArr.push(
new RecurringTxObj(
data.name,
data.user_id,
data.amount,
data.date,
[]
)
);
}
res.status(200).send(recurringTxArr);
})
.catch((err) => {
console.log('Could not find recurring transactions');
res.status(500).send('Could not find recurring transactions');
});
});
router.get('/error', (req, res) => {
throw new Error('Something went wrong');
});
module.exports = router;

mongodb update not working to replace a document (but $set does)

From homework 2_2 of the M101JS course at university.mongodb.com.
Write a program that finds the document with the highest recorded temperature for each state, and adds a "month_high" field for that document, setting its value to true.
The following code should work to update the correct doc in the collection adding "month_high". And the problem is here:
//db.collection('data').update(query, setMonthHigh, function(err, updated) {//OK
db.collection('data').update(query, doc, function(err, updated) {// NOT OK, dunno why
The 2nd update line does not save anything. But if I use the commented update above, it works.
Does anyone have an idea why the 2nd update line isn't working (the one that replaces the whole doc)?
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/weather', function(err, db) {
if(err) throw err;
var options = { 'sort' : [ ['State', 1], ['Temperature', -1] ]};
var lastDoc = null;
var setMonthHigh = {'$set':{'month_high':true}};
var cur = db.collection('data').find({}, {},options);
//var cur = db.collection('data').find({'month_high':true}, {},options);
cur.each(function(err, doc) {
if(err) throw err;
if(doc == null) {
console.log("Document done");
//return db.close();
db.close();
process.exit(0);
}
var query = {'_id' : doc._id};
//db.collection('data').update({'month_high':true}, {$unset:{'month_high':1}}, function(err, updated) {});
//console.dir(doc);
if ( ( lastDoc != null && lastDoc.State != doc.State ) ||
lastDoc == null )
{
doc['month_high'] = 'true';
//db.collection('data').update(query, setMonthHigh, function(err, updated) {//OK
db.collection('data').update(query, doc, function(err, updated) {
// NOT OK, dunno why
if(err) throw err;
console.dir("Update "+updated);
});
console.dir(doc);
}
lastDoc = doc;
});
});
Also, I'm told that using process.exit(0) is a bad hack, but it was the only way I could exit the code without throwing exceptions on return db.close();. If anyone knows a way to exit the code gracefully, that would be great too.
First of all, you have made a mistake in part of your code responsible for updating a database.
db.collection('data').update is an asynchronous function. It means that you cannot execute db.close() without knowing if all updates have been completed. For more details please read: How can I use a cursor.forEach() in MongoDB using Node.js?
Both updates works. However there is one difference between two of them:
db.collection('data').update(query, setMonthHigh, function(err, updated)
updates records with a new field: 'month_high': true <- boolean value
Query to find these records is: db.data.find({'month_high': true})
db.collection('data').update(query, doc, function(err, updated)
updates records with a new field: 'month_high': 'true' <- string value
Query to find these records is: db.data.find({'month_high': 'true'})
Your updated code:
Before run it, first install async library (npm install async)
var async = require('async');
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/weather', function(err, db) {
if(err) throw err;
var q = async.queue(function (doc, callback) {
db.collection('data').update({_id: doc._id}, doc, callback);
}, Infinity);
var options = { 'sort' : [ ['State', 1], ['Temperature', -1] ]};
var lastDoc = null;
var cur = db.collection('data').find({}, {},options);
cur.each(function(err, doc) {
if(err) throw err;
if(doc === null) return;
if ( ( lastDoc !== null && lastDoc.State !== doc.State ) ||
lastDoc === null )
{
doc['month_high'] = true;
q.push(doc, function(err, updated) {
if(err) throw err;
console.log("Update "+updated);
});
}
lastDoc = doc;
});
q.drain = function() {
if (cur.isClosed()) {
console.log('Document done');
db.close();
}
}
});

MeteorJS: Collection always returns count of 0

I have an app that has a collection called Cities.
Right now, all I am trying to do is to get the consoleto print the count of documents in the collection, but it only returns 0
Client.js
Meteor.subscribe('cities');
Meteor.autorun(function() {
Meteor.subscribe('jobs', Session.get('currentIndustryOnet'));
});
Meteor.startup(function(){
if(!Session.get('jobsLoaded'))
Session.set('jobsLoaded', true);
if(! Session.get('map')) {
gmaps.initialize();
}
Deps.autorun(function(){
console.log(Cities.find().count())
});
});
If I log into the mongo shell and run:
db.cities.find().count()
The count returned is 29467, so I know there are records that exist. Not sure what I am doing wrong here
Code Structure:
project_dir/client/client.js
Meteor.subscribe('cities');
Meteor.autorun(function() {
Meteor.subscribe('jobs', Session.get('currentIndustryOnet'), function(){
console.log(Cities.find({}).count());
});
});
project_dir/server/server.js
Meteor.publish('jobs', function(onet_code){
var cursor, options = {sort: {"dateacquired": -1}};
if(onet_code && onet_code != 'all'){
cursor = Jobs.find({onet: onet_code}, options);
} else {
cursor = Jobs.find({}, options);
}
return cursor;
});
Meteor.publish('cities');
project_dir/model.js:
Cities = new Meteor.Collection("cities");
Jobs = new Meteor.Collection("jobs");
Jobs.allow({
insert: function(id) {
return false;
},
update: function(id, options) {
return true;
}
});
createJob = function(options) {
var id = Random.id();
var onet = Session.get('currentIndustryOnet')
Meteor.call('createJob', _.extend({_id: id}, options));
return id;
}
Meteor.methods({
createJob: function(options) {
var id = options._id || Random.id();
Jobs.insert({
_id: id,
lat: options.lat || '',
lng: options.lng || '',
title: options.title,
url: options.url,
company: options.company,
address: options.address,
dateacquired: options.dateacquired,
onet: options.onet,
jvid: options.jvid
});
return id;
}
})
You need to publish your cities collection:
Instead of :
Meteor.publish("cities")
You should have :
Meteor.publish("cities", function() {
return Cities.find()
});

Does Meteor have a distinct query for collections?

I'd like to return distinct fields in my collection. I know these are the docs for mongo operators, but I'm not familiar enough with the query language to know if this is possible?
Meteor.publish("distinctCollection", function() {
return Collection.find({ ... }, fields: { "myField": 1 });
});
Collection.find({}).distinct('myField', true);
To use, put the following in [project]/client/lib/a.js:
LocalCollection.Cursor.prototype.distinct = function (key,random) {
var self = this;
if (self.db_objects === null)
self.db_objects = self._getRawObjects(true);
if (random)
self.db_objects = _.shuffle(self.db_objects);
if (self.reactive)
self._markAsReactive({ordered: true,
added: true,
removed: true,
changed: true,
moved: true});
var res = {};
_.each(self.db_objects,function(value){
if(!res[value[key]]){
res[value[key]] = value;
}
});
return _.values(res);
};