Trigger in cosmos db cannot find the document - triggers

I have a pre trigger for create new item in cosmo db collection.
The trigger will read a meta file and then update the item to be created.
the partition key is /id
and the _sequence document is just a meta document keeps track of how many items we have in the collection.
However, the trigger always raise error "Fail to find the metadata document"
even though it exists in the collection.
Can anyone tell me what I have done wrong?
function updateRefnumber() {
var context = getContext();
var collection = context.getCollection();
var collectionLink = collection.getSelfLink();
var request = context.getRequest();
var itemToCreate = request.getBody();
getAndUpdateSequence();
function getAndUpdateSequence() {
// Get the meta document. We keep it in the same collection. it's the only doc that has .isMetadata = true.
var isAccepted = collection.queryDocuments(collectionLink, "SELECT * FROM root r WHERE r.id = '_sequence'", function (err, feed, options) {
if (err) throw err;
if (!feed || !feed.length) throw new Error('Failed to find the metadata document.');
// The metadata document.
var metaDoc = feed[0];
if (metaDoc.createdDocuments == undefined) {
throw new Error('createdDocuments does not exit on object.');
}
var sequence = metaDoc.createdDocuments += 1;
itemToCreate.refNumber = 'PBC-' + sequence;
// Update/replace the metadata document in the store.
var isAccepted = collection.replaceDocument(metaDoc._self, metaDoc, function (err) {
if (err) throw err;
});
if (!isAccepted)
throw new Error('The call replaceDocument(metaDoc) returned false.')
else
request.setBody(itemToCreate);
});
if (!isAccepted) throw new Error('The call queryDocuments for metaDoc returned false.');
return;
}
}

Related

Axios: How to get data within axios

I created a search for a unique barcode. Therefore the result will be 0 or 1 because it is unique. If barcode is found, I need to get the ID of that record. How do we do this?
axios.get("api/findpatronbarcode?q=" + query)
.then(({data}) => {
this.loanpatrons = data.data;
//COUNT RECORDS
this.countPatrons = this.loanpatrons.length;
console.log(this.countPatrons);
//THE PROBLEM IS THE CODE BELOW. IT RETURNS "Undefined"
// Get the ID of the record
var getID = this.loanpatrons.id;
console.log(getID)
});
You can try like this:
axios.get("api/findpatronbarcode?q=" + query)
.then(({data}) => {
this.loanpatrons = data.data;
//COUNT RECORDS
this.countPatrons = this.loanpatrons.length;
console.log(this.countPatrons);
// KEEP IN MIND THAT "loanpatrons" is Array
// so first get the first member of the Array
// and only then Get the ID of the record
var getID = (this.loanpatrons[0] || {}).id || '';
console.log(getID)
});

Attempting to save subdocument update, deletes the parent

I am attempting to save an update to my subdocument, but when I save the parent document disappears (thus loosing all the data including the update).
Here is my route:
router.put('/input/:parentid/:childid', urlencodedParser, function(req, res, next){
// Update Already Created Incident
async function update(id){
let checkedUnits = [];
let timeEntries = [];
recall = [];
units.forEach(unit => {
if(req.body[unit.id]){
checkedUnits.push(unit._id);
}
});
// console.log(personnel);
personnel.forEach(person => {
if(req.body[person._id]){
let PERSON = {person: {personId: person._id}}
recall.push(PERSON);
}
});
//===================FIND PARENT DOCUMENT===================================//
CallData.findOne({_id: id}, (err, doc)=>{
//====================TARGET CORRECT SUBDOCUMENT by id =====================//
subdoc = doc.incidents.id(req.params.childid);
//===========================UPDATE DOCUMENT=============================//
date = moment(req.body.dispatchDate).format('YYYY-MM-DD')
doc.date=date,
subdoc.incidentNumber = req.body.incidentNumber;
subdoc.callType = req.body.callType;
subdoc.times.dispatch = moment(req.body.dispatchDate).format('MM/DD/YY')+' '+req.body.dispatchTime;
subdoc.times.clear = moment(req.body.clearDate).format('MM/DD/YY')+' '+req.body.clearTime;
subdoc.address.placeName = req.body.locationName;
subdoc.address.streetAddress = req.body.streetAddress;
subdoc.address.apt = req.body.apt;
if(req.body.disposition !== "Choose..."){
subdoc.disposition.selected = req.body.disposition;
}
subdoc.disposition.typed = req.body.other;
subdoc.units = checkedUnits;
subdoc.recall = recall;
//==============Save Document===============//
doc.save(err=>{if(err){console.log(err)}); //<==============No error thrown here.
res.json(doc); //<==================Produces a correct json of the updated doc.
});
}
update(req.params.parentid);
});
Once the above runs on a document it disappears from the database. I am not sure why doc.save is deleting the doc.
I have tried using async/await, and CB. I am unsure how else to select the correct subdocument in the subdocument array. Mongoose's docs say to do the ```parent.sub.id(_id)`` to select it but I have a feeling this is where I am going wrong.
Thank you for any insight.
-Adam
The answer was here:
date = moment(req.body.dispatchDate).format('YYYY-MM-DD')
It was changing the date format and therefore I could not find my data, I thought it was being deleted it was not. Just being changed.
I have corrected the code to:
date = moment(req.body.dispatchDate).format('YYYY/MM/DD')
And now I it works beautifully.
Thanks for the help.

MongoDB How to copy index definitions from one collection to another?

I know there's a way to do db.collection.getIndexes() Which will list all the indexes defined for a collection. Is there a way to copy and create those index definitions to another collection?
There's a lot of them and I don't want to do them one by one.
regarding the duplicated question comment: I do not wish to copy a collection. I wish to export indexes in a format that I can apply to another collection.
For example I have one existing user collection with indexes _id_, name_1, email_1 and website_1
Then I have another collection called usertest, I want to copy indexes from user collection to usertest collection. The following commands works for this scenario:
Copy both index key and index options
var indexes = db.user.getIndexes();
indexes.forEach(function(index){
delete index.v;
delete index.ns;
var key = index.key;
delete index.key
var options = [];
for (var option in index) {
options.push(index[option]);
}
db.usertest.createIndex(key, options);
});
Copy index key only (batch processing)
var indexKeys = db.user.getIndexKeys();
db.usertest.createIndexes(indexKeys);
Hope this will be helpful. Here's the doc: createIndexes
To do this directly in MongoDB do the following,
The following command will generate mongo DB queries for existing indexes of all collections,
db.getCollectionNames().forEach(function(col) {
var indexes = db[col].getIndexes();
indexes.forEach(function (c) {
var fields = '', result = '', options = {};
for (var i in c) {
if (i == 'key') {
fields = c[i];
} else if (i == 'name' && c[i] == '_id_') {
return;
} else if (i != 'name' && i != 'v' && i != 'ns') {
options[i] = c[i];
}
}
var fields = JSON.stringify(fields);
var options = JSON.stringify(options);
if (options == '{}') {
result = "db." + col + ".createIndex(" + fields + "); ";
} else {
result = "db." + col + ".createIndex(" + fields + ", " + options + "); ";
}
result = result
.replace(/{"floatApprox":-1,"top":-1,"bottom":-1}/ig, '-1')
.replace(/{"floatApprox":(-?\d+)}/ig, '$1')
.replace(/\{"\$numberLong":"(-?\d+)"\}/ig, '$1');
print(result);
});
});
The above command will output something like the following, based on the amount of collection you have
db.User.createIndex({"createdAt":-1}, {"background":true});
db.User.createIndex({"updatedAt":-1}, {"background":true});
db.Login.createIndex({"loginDate":-1}, {"background":true});
So after executing this, copy the MongoDB queries that are generated above to create the indexes to the new collection, Change the collection name in that then execute it.
For eg: to copy all indexes belonging to the User collection to the UserNew collection, I will rename the query's old collection name to new like the following and execute it, that is it, now you have all the indexes copied to a new collection from the old one.
db.UserNew.createIndex({"createdAt":-1}, {"background":true});
db.UserNew.createIndex({"updatedAt":-1}, {"background":true});
Credits: http://aleksandrmaiorov.com/2019/04/29/mongo-how-to-copy-indexes-from-one-database-to-another/
Thank you for the answer from Rocky and Bloke which helped me a lot
here is the consolidated version as suggested by Bloke.
and in PRODUCTION. we would like to make sure the background: true
is used to avoid slave halt query when indexes creation replicated.
var indexes = db.user.getIndexes();
// we skipped the __id__ indexes and set the default background: true option
indexes.forEach(function(index){
if(index.name =='_id_'){
print("we are skip the _id_ index")
}else{
delete index.v;
delete index.ns;
var key = index.key;
delete index.key
var options = {};
for (var option in index) {
options[option] = index[option]
}
options['background'] = true;
printjson(key);
printjson(options);
db.usertest.createIndex(key, options);
}
});
Rocky Li's answer was helpful but did not create the index options properly at the time of writing (It gathered the option values but not the keys). The following modification worked for me:
var indexes = db.user.getIndexes();
indexes.forEach(function(index){
delete index.v;
delete index.ns;
var key = index.key;
delete index.key
// uncomment if you want to ensure creation is in background
//if(!('background' in index))
//index['background'] = true;
db.user.createIndex(key, index);
});
Copy all indexes from one database another database
use firstDbName;
var indexKeyArray = [];
db.getCollectionNames().forEach(function(collection) {
var indexKeys = db[collection].getIndexKeys();
var base = {};
base["name"] = collection;
base["indices"] = indexKeys
indexKeyArray.push(base);
});
#printjson(indexKeyArray);
use destinationDbName;
indexKeyArray.forEach(function(data) {
db[data.name].createIndexes(data.indices);
});

How to get auto Id after upsert on a persisted model in loopback?

I have a some models generated from postgresql db using looback-connector postgresql. Id column of these models is a auto incremented integer column of postgresql db.
1) I have a remote method added on one of persisted models, where i perform simple update or insert(upsert.
Car.CreateOrUpdateCar = function (carobj, req) {
Car.upsert(Carobj, function (err, Car) {
if (err)
console.log(err);
else {
req(err, Car);
}
});
};
2) have added a remote hook to execute after this remote method.
Car.afterRemote('CreateOrUpdateCar', function (context, remoteMethodOutput, next) {
//Remaining code goes here
next();
});
3) I want to use Id of newly inserted row in step (1), in the remote hook mentioned in step (2)
I don't have much idea about postgresql db. But Try it like this
var carObj;
Car.CreateOrUpdateCar = function (carobj, req) {
Car.upsert(Carobj, function (err, Car) {
if (err)
console.log(err);
else {
req(err, Car); // Your Car object contains final result after upserting along with Id
carObj = Car;
}
});
};
Now you can get id by using carObj.id and you can use it where ever you want. I hope this helps
You can access to generated id in remote hook like this :
Car.afterRemote('CreateOrUpdateCar', function (context, remoteMethodOutput, next) {
var genId = remoteMethodOutput.id || context.result.id;
next();
});

Create an object from multiple database collections (SailsJS, MongoDB, WaterlineJS)

I'm very new to Sails and noSQL databases and I'm having trouble gathering information together from different collections. Basically I need to gather an object of items from one collection and then use a foreign key stored in that collection to add data from a separate collection so the whole thing can be sent as one object.
Currently I find all the items in a collection called Artwork, then I'm using a for loop to iterate through the artworks. I need to use an id stored in Artworks to query a collection called Contacts but having successfully found the contact I am unable to pass it back out of the function to add it to the Artwork object.
find: function ( req, res, next ) {
Artwork.find().done( function ( err, artwork ) {
// Error handling
if (err) {
return console.log(err);
} else {
for ( x in artwork ) {
var y = artwork[x]['artistID'];
// Get the artsists name
Contact.find(y).done( function( err, contact ) {
// Error handling
if ( err ) {
return console.log(err);
// The Artist was found successfully!
} else {
var artist = contact[0]['fullName'];
}
});
artwork[x]['artistsName'] = artist;
}
res.send(artwork);
}
});
}
The result of the above code is an error thrown that tells me 'artist' is undefined. The variable is not being passed outside the function?
Any advice greatly received.
Sails is about to release an update that will include associations. In the meantime, here's an answer for how you can accomplish it using async. https://stackoverflow.com/a/20050821/1262998