Removing doc and reading its fields - node.js

In my app I need a function that removes docs and giving me the removed doc fields. The docs for the driver are not clear about the callback of deleteMany. It returns a result that is deleteWriteOpResultObject. I don't know how to get the deleted doc fields from that.

You may use findAndModify operation with remove: true and fields: {your_fields} if you need to get and delete a single document. In case you have to remove and select multiple records, you may execute findAndModify multiple times or call find, wait the results and remove them all by IDs.

Related

mongodb updateOne updates document but it returns like it didn't

I've been building a backend app with NodeJS and MongoDB.
Until today, I could successfully check every result of updateOne function.
But now, it returns this:
{"acknowledged":false,"modifiedCount":0,"upsertedId":null,"upsertedCount":0,"matchedCount":0}
The problem is, it returns this but it updates the document? How can I solve this bug?
From mongoDB documentation:
The method returns a document that contains:
matchedCount containing the number of matched documents
modifiedCount containing the number of modified documents
upsertedId containing the _id for the upserted document.
A boolean acknowledged as true if the operation ran with write concern or false if write concern was disabled
So you need to check modifiedCount for check the numeber of document you updateting.
If you need to update just one document i suggest to use findOneAndUpdate(filter, update)

Deleting all documents in CouchDB

I have a database and I want to truncate all records, I know it is possible to just add a _deleted key to every document or call db.delete() on CouchDB-python library. I am using the delete of couchdb-python but it does not seem to work when I fetch all the documents and then call .delete on each document excluding design documents.
Here is my code.
docs = get_db().view('_all_docs', include_docs=True)
for i in docs:
if not(i['id'].startswith('_')):
get_db().delete(i)
This is the error. Because the result from _all_docs is returning a id instead _id.
File "C:\Users\User\AppData\Local\Programs\Python\Python36-32\lib\site-packages\couchdb\client.py", line 625, in delete
if doc['_id'] is None:
KeyError: '_id'
My question is how do I fetch all documents that returns _id instead of just the id? Or is there any way around this?
In couchdb-python a view query returns a list of couchdb.client.Row objects, not a list of the docs. You need to pass an attribute doc to that delete, i.e. get_db().delete(i['doc']).
From performance perspective, however, it's better to use bulk api. With couchdb-python it should look something like this:
rows = get_db().view('_all_docs', include_docs=True)
docs = []
for row in rows:
if row['id'].startswith('_'):
continue
doc = row['doc']
doc['_deleted'] = True
docs.append(doc)
get_db().update(docs)
Deleting documents from CouchDB you can create in two step:
create a view (with filtering the documents you want to delete)
use the view to delete all documents using the view
I have written a tool for this.

Mongoose/MongoDB - Delete and Insert as one transaction

I wanted to delete certain set of documents in the mongo collection and insert new records, in case if the insert fails I want to rollback the delete. Basically, it is either both or none. Someone know what is the best approach for this. I'm using mongoose and nodejs.
Try to use promises. Insert one more field to your schema like isDeleted. When you delete some document set it to true and in the success of promise of delete, if the document successfully inserted delete that record permanently if you want.
Like this
db.collection.findOneAndUpdate(query)
.exec()
.then(
// write your insert logic here
db.collection.insert(query)
.exec()
.then()
.catch(
//if anything goes wrong set isDeleted
//to false again.
)
)
.catch()
I'd add a 'hidden' flag, then set the flag to true on some records insert new ones then depending on insert failure or success delete hidden objects or unhide them
What you need is a "Transaction".
A transaction is a unit of work, composed of a series of operations that you want either to succeed together, or fail together when one or more of the operations fail.
The following link explains in detail the use of transactions in nodejs and mongodb:
https://www.mongodb.com/docs/drivers/node/current/fundamentals/transactions/

How can i update all object in an array without id at MongoDB

I call the Elements with find() method and after than i want to update all. For example:
db.collection.find().limit(10).update({$set: {'column' : 'value'}});
how can i fix this?
If you want to apply update to every document in collection, use {multi:true} option
db.collection.update({},{$set: {'column' : 'value'}},{multi:true});
For more detail, see collection.update
However, if you want to update selected number of documents, you'll be taking longer route.
db.collection.find().limit(10).forEach(function(o){
o.column = some_value; // replace some_value with real one.
db.collection.update({_id:o._id},o);
});
By default it updates only the first 1 document it found. You need to add multi = true as an option to update() to update all. Unfortunately, update() doesn't have limit option so you can limit it to 10.
You might have to do find() with limit first and then update each document separately like mentioned in this post:
How to limit number of updating documents in mongodb

How to efficiently bulk insert and update mongodb document values from an array?

I have a Tags collection which contains documents of the following structure:
{
word:"movie", //tag word
count:1 //count of times tag word has been used
}
I am given an array of new tags that need to be added/updated in the Tags collection:
["music","movie","book"]
I can update the counts all Tags currently existing in the tags collection by using the following query:
db.Tags.update({word:{$in:["music","movies","books"]}}, {$inc:{count:1}}), true, true);
While this is an effective strategy to update, I am unable to see which tag values were not found in the collection, and setting the upsert flag to true did not create new documents for the unfound tags.
This is where I am stuck, how should I handle the bulk insert of "new" values into the Tags collection?
Is there any other way I could better utilize the update so that it does upsert the new tag values?
(Note: I am using Node.js with mongoose, solutions using mongoose/node-mongo-native would be nice but not necessary)
Thanks ahead
The concept of using upsert and the $in operator simultaneously is incongruous. This simply will not work as there is no way to different between upsert if *any* in and upsert if *none* in.
In this case, MongoDB is doing the version you don't want it to do. But you can't make it change behaviour.
I would suggest simply issuing three consecutive writes by looping through the array of tags. I know that's it's annoying and it has a bad code smell, but that's just how MongoDB works.

Resources