Elasticsearch _bulk update issue giving VersionConflictEngineException message - node.js

I am using elasticsearch in one of my project. I am facing an issue while updating a record. The error message that I am getting is:-
{ _index: 'makes',
_type: 'make',
_id: '55b8cdbae36236490d00002a',
status: 409,
error: 'VersionConflictEngineException[[makes][0] [make][55b8cdbae36236490d00002a]: version conflict, current [168], provided [167]]' }
Using ES bulk api. My application is in node.js.
Let me share my code too:-
var conditions = [];
conditions.push({
update: {
_index: config.elasticSearch.index,
_type: config.elasticSearch.type,
_id: id
}
});
conditions.push({
doc: {
published: true
}
});
client.bulk({
body: conditions
}, function(err, resp) {
console.log(resp);
console.log(resp.items[0].update);
return res.send({success: true, message: "Shows updated successful"})
});
The below is the value of conditions array:
[ { update:
{ _index: 'makes',
_type: 'make',
_id: '55b8cdbae36236490d00002a' } },
{ doc: { published: true } } ]

When you start querying a record, its response with the record including the version of that record. When you want to update it, but before it, it has been updated by another, the record in the database has a higher version than what the client thinks.
This may happen because some operation are still in queue, so you get the unprocessed record (hence lower version). When this happens, try https://www.elastic.co/guide/en/elasticsearch/reference/1.6/indices-refresh.html:
curl -XPOST 'http://localhost:9200/{your_index}/_refresh'
Then call your method again

Related

MongoDB Update & Aggregate Problem: Skipping over aggregation

I have two tables, one for messages to be logged and one that is for each member of the group. When a message is upvoted, I want to add an entry for the message and push each reaction on that message to an array.
Every time a reaction is added I want to update the member table to reflect the sum of all of the reaction.value fields.
This is the code I have written to do so. When this runs from a sandbox I made in VisualStudio using a MongoDB add on it runs fine, however when ran using my app, only the message document is added and without any error it appears to skip the aggregation to the member document.
Here is the code I am using to insert the documents to the database and to aggregate once the document is inserted:
await mongodb.collection("Messages").updateOne({ _id: reaction.message.id.toString()},
{
$set:{
authorid: reaction.message.author.id,
author: reaction.message.author.username
},
$push: {
reactions: {
reauth: reAuth,
reaction: reaction.emoji.name,
removed: false,
value: actualKarmaDB,
}
}
}, {safe: true, "upsert": true})
await mongodb.collection("Messages").aggregate([
{
$match: {
_id: reaction.message.id
}
},
{
$project: {
_id: "$authorid",
username: "$author",
messageKarma: {$sum: "$reactions.value"},
}
},
{ $merge: {
into: "Members",
on: "_id",
whenMatched: "replace",
whenNotMatched: "insert"
}
}])
Also here is a look at what the insertion into “Messages” looks like:
In this case the answer was due to mongoose not supporting merge for aggregation. Had to use $out.
Additionally this is a known issue with Mongoose Node.js, see here:
Mongodb node.js $out with aggregation only working if calling toArray()

The date is not updated in MongoDB

When trying to update the date inside the MongoDB document, nothing is updated.
To update, I send a request to NodeJS like this:
collection.updateOne(
{ _id: ObjectId(...) },
{ $set: { 'field1.field2.0.date': new Date('2020-02-01T00:00:00Z') } },
callback
)
The task uses the npm package mongodb#2.3.26 and MongoDB 3.6.20.
I tried to send the '2020-02-01T00:00:00Z' as a value - it is not updated. I tried to update the database version - it didn't help. I tried to update the driver version - it didn't help.
It is interesting that such a request goes through Robo3T and updates the value correctly.
Could you please tell me how to update the date inside the document for MongoDB?
UPD: Structure of document
const document = {
field1: {
exp: 1,
field2: [
{
name: "test",
date: 2019-10-01 00:00:00.000Z
}
]
},
settings: {
sharedTill: 2022-10-01 00:00:00.000Z
},
updatedBy: 'Vadim Prokopchuk'
}
UPD2: Added Response from MongoDB
MongoDB returned data and does not return an error.
the syntax you're using isn't correct.
Refer the query below, it would work
collection.updateOne(
{ _id: ObjectId(...) , 'field1.field2.name':"test"},
{ $set: { 'field1.field2.$.date': new Date('2020-02-01T00:00:00Z') } },
callback
)
Here, we are finding the element of the array which matches our condition and then updating the date of that particular element of the array.

Why update_by_query returning "socket hang up" error when trying to update large number of documents?

I am trying to add/update one field in all documents of an index using minimal queries but I am getting errors: socket hang up and then version conflicts.
Referring to this update_by_query, I tried a similar query for my use case i.e
esClient.updateByQuery({
index: "test_index",
type: "_doc",
body: {
query: {
match_all: {}
},
script: {
lang: "painless",
source: `ctx._source.name=params.name;`,
params: { name: "raghu" }
}
}
});
After some more research, I added this conflicts: "proceed" option after which version conflict does not arrive but I am still getting socket hang up error.
================================================================================================
Though I can solve this using the following solution and it is working fine:
const limit = 10000;
//Iterating infinitely
while (true) {
//adding required field for every batch if it doeas not exist
const result = await esClient.updateByQuery({
index: "test_index",
type: "_doc",
body: {
query: {
bool: {
must_not: {
exists: {
field: "name"
}
}
}
},
script: {
lang: "painless",
source: "ctx._source.name=params.name;",
params: { name: "raghu" }
}
},
size: limit,
conflicts: "proceed"
});
const { updated } = result;
//stop once updated result length is less than limit
if (updated < limit) {
//Done
return result;
}
}
I am using Elastic Search v6.3.0 and NodeJs v10+.
Can anyone explain why am I getting that error in the first case?

How to get all revisions document with single request in couchdb?

I use nano.js as couchdb driver in my express app. i managed to get document revision's id with command like this
db.get(id, { revs_info: true }, function(err, inventory){
res.send(inventory);
})
which returns the latest revisions with _revs_info in it. Unfortunately _rev_info only includes revision number and availability status.
{ _id: 'doc',
_rev: '3-825cb35de44c433bfb2df415563a19de',
_revs_info:
[ { rev: '3-825cb35de44c433bfb2df415563a19de',
status: 'available' },
{ rev: '2-7051cbe5c8faecd085a3fa619e6e6337',
status: 'available' },
{ rev: '1-967a00dff5e02add41819138abb3284d',
status: 'available' } ]
}
so how to get all revision's document with single request in couchdb ?

Node.js driver "mongodb" implementation of findAndModify() - how to specify fields?

I'm trying to pop and retrieve an element out of an array stored in a document. I can't use $pop since it doesn't return the POPed element. I'm trying to use findAndModify() instead. It works in the shell console, but I'm having troubles getting it to work using the mongodb node.js driver (https://www.npmjs.org/package/mongodb).
my document structure looks like so:
{ _id: '1', queue: [1,2,3]}
In mongo shell, I do:
> db.collection.findAndModify({ query: { _id: 1 },
update: { $pop: { queue: -1 } },
fields: { queue: { $slice: 1 } }, new: false })
$slice ensures that the returning document shows the element that has just been poped. To clarify, I'm not interested in what is in the queue, I'm only interested in what I have just popped out of the queue.
returns:
< {_id: 1, "queue": [1]} // yes, it works!
Using the mongodb library, I don't know how to specify the $slice: 1, it doesn't seem to be supported in the options(?):
> db.collection('collection').findAndModify(
{ _id: 1 },
[],
{ $pop: { queue: -1 }, queue: { $slice: 1 } },
{ new: false },
function(error, results) {
if(error) {
console.log(error);
}
console.log(results);
}
);
returns:
< MongoError: exception: Field name duplication not allowed with modifiers
Basically - where should I put the "queue: {$slice: 1}" part in the nodejs query to make this work? Is it even supported in the node.js driver implementation?
Also, it doesn't seem like findAndModify() is meant to be used this way. If $pop was returning the POPed value, it would be ideal. Any suggestions on how to do this?
Thanks,
- Samir
It seems like that the node.js implementation does not support the 'fields' operand at all.
We've figured out this work around:
1) We store each element in it's own document, instead of an array within the same document.
2) Now findAndModify works like so:
db.collection('collection').findAndModify(
{}, // findAndModify will match it to the first document, if multiple docs are found
[],
{},
{remove: true, new: false }, // returns & removes document from collection
function(error, results) {
if(error) {
console.log(error);
}
console.log(results);
}
);
Some good links that helped us and might help you if you have a similar issue:
https://blog.serverdensity.com/queueing-mongodb-using-mongodb/
http://www.slideshare.net/mongodb/mongodb-as-message-queue

Resources