In the following is the section of code :
Profile is a mongoose shcema object and contains multiple key-value pairs and the function of the code is to update Profile using findOneAndUpdate method passing in profileFields to $set which contains the new key-value pairs.
let profile = await Profile.findOne({ user: req.user.id });
if (profile) {
profile = await Profile.findOneAndUpdate(
{ user: req.user.id },
{ $set: profileFields },
{ new: true }
);
console.log(profile);
return res.json(profile);
}
This code works fine when a value for a key is changed.
eg. Profile.githubusername was abcd and is changed by passing profileFields(in which githubusername is xyz) to $set in the findOneAndUpdate method.
But the code fails when a key-value pair is completely removed.
eg. profileFields object does not contain githubusername key.
In such case the earlier previously stored value of Profile.githubusername persists.
But I need all existing information for profile to be replaced by profileFields such that if a key-value pair is missing from profileFields it is also removed from profile.
Is there a way to achieve this?
TIA
Edit :
I added the following before making the call to findOneAndUpdate(). But this still doesn't work.
let profile = await Profile.findOne({ user: req.user.id });
// for (key in profile)
// console.log(key);
for (key in profile) {
if (Object.keys(profileFields).indexOf(key) === -1) {
console.log('missing key: 'key);
profileFields[key] = '';
}
}
When I console.log(profile) I get:
{
skills: [ 'HTML' ],
_id: 60142f8f9a5bff1f08653478,
user: 60142dc89a5bff1f08653477,
company: 'Self Employed',
bio: 'Useless international',
status: 'Student or Learning',
experience: [],
education: [],
date: 2021-01-29T15:53:51.693Z,
__v: 10,
location: 'Ahemdabad, Gujrat, India',
githubusername: 'k'
}
From what I understand skills, _id, user, company, bio ... githubusername are the only keys in this object.
But on running a for (key in profile) loop I get a lot a other keys as well ,some are :
$__
isNew
errors
$locals
$op
_doc
$init
db
discriminators
schema
collection
$__originalValidate
$__save
$__validate
$__remove
$__deleteOne
$__init
$isMongooseModelPrototype
$__handleSave
save
$__delta
$__version
increment
$__where
remove
delete
How can I loop through only the user defined keys?
You can try:
delete mongooseObject["$init"]
it will delete your key and then u can manipulate other keys
I am having trouble trying to get a Collection.upsert to work in Meteor 1.4.3.2.
My app pulls in active listings from eBay and inserts them into the database if they don't already exist, otherwise it updates the listing that is already stored. So, what I am trying is the following in a meteor method:
let upsertObj = {$set: {}};
const account = ListingAccounts.findOne( ... );
if (!account) // throw an error because account info is required by schema
upsertObj.$set['account.id'] = account._id;
upsertObj.$set['account.username'] = account.username;
upsertObj.$set['account.nickname'] = account.nickname;
// ... also gets other listing data such as listingId, title, condition, etc...
return Listings.upsert({listingId: eBayListingID}, upsertObj);
There are other values that are nested similarly to the account details above, and they all seem to work. I've logged the final upsertObj object and the values are valid and comply with my schema (SimpleSchema), but just for good measure, here is an excerpt of the final upsert object I am logging on the server just before the upsert happens:
{ '$set':
{ 'account.id': 'trustmethisisvalidstring',
'account.username': 'ValidAccountNameString',
'account.nickname': 'ValidAccountNicknameString',
/* more name:values below this */
}
}
Here is an excerpt from my schema (aldeed:simple-schema 1.5.3)
ListingsSchema = new SimpleSchema({
account: {
type: Object
},
"account.id": {
type: String,
optional: true // added after question asked
},
"account.username": {
type: String,
optional: true // added after question asked
},
"account.nickname": {
type: String,
optional: true // was always optional
},
...
});
I am receiving the error on the client with the following details:
[{"name":"account.id","type":"required","value":null},{"name":"account.username","type":"required","value":null}]
with the reason reason: "Id is required"
This is the first time I've tried using upsert and I can't help but feel I am missing the mark on something. Maybe my syntax is off, or maybe I'm just not using bracket notation correctly? I don't know, the Meteor docs unfortunately do not have any examples that I could find.
Any assistance or clarification on using Upsert would be super appreciated, thank you!
In my app I have an endpoint that allows a user to create a new document by simply passing something like this:
{ name: { long: "some name" } }
Now, the relevant portion of the model for this document looks like this:
name: {
long: {
type: String,
trim: true
},
short: {
type: String,
trim: true
}
}
As you can see, I don't have "short" set to "unique: true". However, the user is getting this error:
"errmsg": "E11000 duplicate key error collection: hr.agencies index: name.short_1 dup key: { : null }"
So, clearly the problem here is that once you have more than one "name.short" with a value of null, its producing a dupe error. However, since I don't have unique set to true in the model, I'm not sure why it's enforcing this as a rule.
What could the issue be here, and how can I resolve it? Is there a way I can explicitly say, don't enforce uniqueness on this field?
Try to remove the index from the short key using
db.collection.dropIndex({ "name.short": 1 })
I am running the latest, as of 5.3.2016, minified Lokijs from Lokijs.org and NW.js v0.12.3-win-x64. I have a document already saved in Lokijs:
"collections":[{"name":"admins","data":[{"username":"erik","meta":{"revision":1,"created":1459028934981,"version":0,"updated":1462333795190},"$loki":1}],"idIndex":[1],"binaryIndices":{},"constraints":null,"uniqueNames":["username"],"transforms":{},"objType":"admins","dirty":true,"cachedIndex":null,"cachedBinaryIndex":null,"cachedData":null,"transactional":false,"cloneObjects":false,"cloneMethod":"parse-stringify","asyncListeners":false,"disableChangesApi":true,"autoupdate":false,"ttl":{"age":null,"ttlInterval":null,"daemon":null},"maxId":2,"DynamicViews":[],"events":{"insert":[null],"update":[null],"pre-insert":[],"pre-update":[],"close":[],"flushbuffer":[],"error":[null],"delete":[null],"warning":[null]},"changes":[],"username":{"name":"username","regExp":{}}}.
I am trying to generate an error when I attempt to insert a duplicate key value. I have added a unique constraint on the 'username' key in this collection and have verified the collection.uniqueNames array contains 'username'.
When I run the code below, as expected, no additional documents are inserted into the collection.data array and the database is saved. However, no errors are generated. Also, when I console.log the document object after the insert method has run, it changes to:
Object {username: "erik", meta: Object, $loki: 2}.
When I change the key value to something else, the unique document is then inserted and saved properly.
How do I go about generating an error when attempting to insert a document containing key(s) that violate unique constraints? Thank you.
insertDocument: function(objParameters) {
var collection = objParameters.insert.collection;
collection.ensureUniqueIndex('username');
var document = {username: ''};
document.username = 'erik';
collection.on('error', function(err) {
return console.log(err);
});
collection.insert(document);
return thisModule.$body.triggerHandler('app.database.save');
}
EDIT: loki.db to test clone
{"filename":"loki.db","collections":[{"name":"test","data":[{"name":"erik","meta":{"revision":0,"created":1462493328062,"version":0},"$loki":1}],"idIndex":[1],"binaryIndices":{},"constraints":null,"uniqueNames":["name"],"transforms":{},"objType":"test","dirty":true,"cachedIndex":null,"cachedBinaryIndex":null,"cachedData":null,"transactional":false,"cloneObjects":true,"cloneMethod":"parse-stringify","asyncListeners":false,"disableChangesApi":true,"autoupdate":false,"ttl":{"age":null,"ttlInterval":null,"daemon":null},"maxId":2,"DynamicViews":[],"events":{"insert":[null],"update":[null],"pre-insert":[],"pre-update":[],"close":[],"flushbuffer":[],"error":[null],"delete":[null],"warning":[null]},"changes":[]}],"databaseVersion":1.1,"engineVersion":1.1,"autosave":false,"autosaveInterval":5000,"autosaveHandle":null,"options":{},"persistenceMethod":"fs","persistenceAdapter":null,"verbose":false,"events":{"init":[null],"loaded":[],"flushChanges":[],"close":[],"changes":[],"warning":[]},"ENV":"NODEJS"}
Code to test clone:
var loki = require('lokijs-1.3.min.js');
var db = new loki();
var collection = db.addCollection('test', {
clone: true,
unique: 'name'
});
collection.on('error', function(error) {
return console.log(error);
});
collection.insert({ name: 'erik'});
collection.insert({ name: 'erik'});
db.saveDatabase();
If you don't use clone: true then you need to call coll.update(document) to force index recomputation, which will trigger the error.
According to MongoDB's documentation a call to save will create a new document, or update an existing document if _id is provided. Mongoose's documentation is less detailed and does not go into whether it will insert or update.
I am attempting to use Mongoose's save function to update a document, but I keep getting the error:
{"error":{"name":"MongoError","code":11000,"err":"insertDocument ::
caused by :: 11000 E11000 duplicate key error index:
staging.participants.$_id _ dup key: { :
ObjectId('5515a34ed65073ec234b5c5f') }"}}
Does Mongoose's save function perform an upsert like MongoDB's save function or is it just performing an insert?
What defines whether the save will be an insert or an update is the isNew flag, as you can see here.
This flag is set automatically to false when the document instance is returned from a find query (or any of its variations). If you are instantiating the document manually, try setting this flag to false before saving it:
var instance = new Model({ '_id': '...', field: '...' });
instance.isNew = false;
instance.save(function(err) { /* ... */ });
There is also an init function, that will initialize the document and automatically set isNew to false:
var data = { '_id': '...', field: '...' };
var instance = new Model();
instance.init(data, {}, function(err) {
instance.save(function(err) { /* ... */ })
});