OK this should be fairly simple so I think I may be doing a thinking mistake.
I have an existing document. I serve it to the client, together with its ObjectId. The client modifies, and wants to update the document. So it comes with the id - looks to me a good choice to identify which document I want to update (?).
But I get an error:
[MongoError: Mod on _id not allowed]
This is the code which updates (via HTTP PUT):
id = req.body._id
Item.update({'_id': id }, req.body, (err) ->
So you need to remove the _id key from the "update" object you send. _.omit can facilitate this.
Item.update {_id: req.body._id}, _.omit(req.body, '_id'), (err) ->
Aside: I see people code like this often. Taking input from the browser and just shoving it into your database is a terrible idea from a data integrity and security perspective. Just like most businesses don't just leave their accounting ledgers out on the counter with a pen and ask the customers to write in there unsupervised. Consider enforcing your data schema, authorization, and some validations.
Related
I have only rev id and now I want to retrieve data by rev id in the Couch Db.
So you wish to fetch any document that has a specific _rev, regardless of its _id. Leaving aside the obvious "why???" here, there is nothing in the CouchDB API that supports this, as the rev is not intended to be used without a corresponding id.
But if you really want to do this, I guess you could create a view that emits the _rev as the key and then query the view:
function (doc) {
emit(doc._rev, 1);
}
But note: this is a really bad idea.
I am using MongoDB with Node for a relatively simple web application that involves users signing up and authenticating their login information. I have experience with relational DB's, but am fairly new to the NoSQL game. I am wondering if I am efficiently using the NoSQL database with the current format of my data storage?
My code as of now to save a user looks like so:
db.users.save({email: req.body.email, display_name: req.body.displayName, password: req.body.password}, function(err, saved) {
if( err || !saved )
console.log("User not saved");
else
console.log("User saved in MongoDB");
});
What is happening here is that each user is being generated his or her own document in a MongoDB "collection." I am wondering if this is going to slow things down when the user base becomes relatively large, and I need to quickly find users for authentication?
Any answer that can help me out conceptually or point me in a direction to learn more would be greatly appreciated!
In MongoDB, what's right and what's wrong depends mostly on how you are going to interact with your data. But one document per user seems like a viable strategy for most use-cases.
To speed up retrieval of users, remember to add indexes for those fields you want to retrieve them by.
In this case, the document you save has no _id field. That means a new document will be generated with a newly generated _id, even when there is already an entry with the same values in the database. Is this what you want? When you want to use the .save(doc) function for updating an existing document, you need to have the _id of the document with the same value as the one you want to update.
Ok so I have a pretty simple DB setup in a MEAN app (node, mongoose, mongo) where I have Book records, and User records. A book has a single Owner, and can have any number of shared users which are stored in an array in a field called sharedWith:. Originally I was storing the user records with an email address as the _id field. I now realize this was a dumb move on my part because if someone wants to change their email address it effectively cuts them off from their books.
The app is not live yet, so it's not a fatal mistake.
My question is, once I revert the User documents to using the original hash value for _id, and store those in the Owner and sharedWith fields in the book documents, will I have to query each hash just to retrieve the actual usable user data?
I know mongoose has a .populate() method which will resolve sub documents, but as for inserting them? Will I POST the users as email addresses, then query each and store the resulting hashes? I can do this manually, but I wanted to make sure there is not some secret mongo-sauce that can do this in the DB itself.
Thanks!
If you have the _id available in the frontend for the user. You can directly share him a book by adding the _id to the sharedWith array of a book. But if you don't have the _id of the user available in the frontend, you need to manually get the _id by querying with the email and then store the _id in the sharedWith. As to retrieve the books, populate is indeed the best option to use to get user data.
And to get all books shared with a user you can do something like this,
Book.find({sharedWith:user1._id},function(err,docs){ });
This query can be made efficient if you use an index on sharedWith but that depends on your use case.
Basic problem
I have some large, but logically organised documents - and would like to perform updates on just a sub-section of an individual document.
Example
Given this simple document:
_id: 123456,
_rev: 3242342,
name: 'Stephen',
type: 'Person',
hobbies: [ 'sky-diving' ]
In my application I might have an addHobbies method, that would use a view that just retrieves:
_id: 123456,
_rev: 3242342,
hobbies: [ 'sky-diving' ]
So that it can then add an additional hobby to the hobbies array, and then PUT just this sub-set of data back to the document.
Question
As I understand it, CouchDB [1.2] does not allow partial updates like this, and so I believe it would be necessary to grab the whole document during the save operation, merge my changes, then PUT the whole document back on every single save.
Is there another way of doing this (am I wrong about CouchDB's capabilities)?
Are there any libraries (I'm using express on node.js) to handle this kind of operation?
You are correct. That is, in fact, what document database means: check-outs and check-ins.
You can create (or use) shim code to simulate what you want, letting you focus on the important parts. On the server side, you can use update functions.
There are many solutions on the client side.
cradle.js will give you fake partials updates with the merge method.
If you only want to update one or more attributes, and leave the others untouched, you can use the merge() method:
db.merge('luke', {jedi: true}, function (err, res) {
// Luke is now a jedi,
// but remains on the dark side of the force.
});
https://github.com/cloudhead/cradle/
Related, and also for Node.js is Transaction for performing arbitrary atomic transactions on CouchDB documents.
I would say that cradle is currently missing a real partial update feature, which would also support updating a path to a key inside the field value's JSON data, like Apache demonstrates here, rather than being limited to updating only a single key in a document, like the db.merge method.
In fact, looking at the cradle source, I see that there is a Database.prototype.update method (in lib/cradle/document.js), but this method doesn't seem to be documented.
It would be elegant of this could be made an integral part of cradle, eliminating the need to do separate requests to CouchDB view's updates only for partial updates.
i have one conceptual question about designing data model in mongo db.
I have some record for "lists". Each list is "one row" record with id, descr, createdBy etc. fiels. But now i have a requirement that each "list" can be shared with other users. What is the best way to design/re-design the model so when user login to see "lists" that he created and "lists" that was shared with him? I was thinking of creating new field "sharedWith" in which all usernames with which "list" is shared to be put separated with comma(or something else). And then when request is made to search in this field. But somehow this approach doesn't seem to me very useful. Can you give me some advice or guidelines ?
I'm using nodejs with mongoose.
Thanks!
User: {
...
myLists: Array<ListObject>
sharedLists: Array<ListObject>
};
ListObject: {
...
owner: User,
sharedWith: Array<User>
};
That would seem a sensible design to me.