MongoDB error on update method during multithreading - java

i'm working with Apache Storm and i want to write on a MongoDB database but, sometimes, it throws an exception of
Caused by: com.mongodb.MongoException$DuplicateKey: { "serverUsed" : "127.0.0.1:27017" , "ok" : 1 , "n" : 0 , "updatedExisting" : false , "err" : "E11000 duplicate key error collection: TesiMarco.UserPostNew_Hampshire index: _id_ dup key: { : \"mainelyinspired\" }" , "code" : 11000}
while using parallelism option. In particular my bolt was executing:
public void execute(Tuple input, BasicOutputCollector collector) {
String user=input.getString(0);
DBObject query=new BasicDBObject("_id",user);
DBObject toUpdate=new BasicDBObject("$inc",new BasicDBObject("numeroPost",1));
collection.update(query,toUpdate,true,false);
}
but it finds duplicated error on key. How can i execute this part multithreading?

Related

Can I make a MongoDB Text Index on a field in a Document that is nested in another Document? (Java)

I have a document that has a nested document set as the "name" variable:
Document{{name=Document{{he=דמטריוס הכרונוגראף, en=Demetrius the Chronographer}}}}
It is contained in a mock database that I am meant to implement search functionality into. I would like to Index the "name" field
of the documents in my collection to quicken the time complexity of a standard collection.find() function, but my name field is set as a Document in which the multiple names are contained in an array.
I would like to be able to index the "he" variant, and "en" variant separately so I can search both fields, but am not sure how to do that via the Java driver. Currently, I am trying to use:
db.getCollection(collectioName).createIndex(text(name.en));
However, I get an error message that reads:
Exception in thread "main" com.mongodb.MongoCommandException: Command failed with error 67 (CannotCreateIndex): 'Error in specification { key: { $text: { $search: "name.en" } }, name: "$text_", ns: "60d4a208049d3506e1c36083_alhatorah.people" } :: caused by :: Values in v:2 index key pattern cannot be of type object. Only numbers > 0, numbers < 0, and strings are allowed.' on server cluster0-shard-00-02.l1p7n.mongodb.net:27017. The full response is { "operationTime" : { "$timestamp" : { "t" : 1625086457, "i" : 22 } }, "ok" : 0.0, "errmsg" : "Error in specification { key: { $text: { $search: \"name.en\" } }, name: \"$text_\", ns: \"60d4a208049d3506e1c36083_alhatorah.people\" } :: caused by :: Values in v:2 index key pattern cannot be of type object. Only numbers > 0, numbers < 0, and strings are allowed.", "code" : 67, "codeName" : "CannotCreateIndex", "$clusterTime" : { "clusterTime" : { "$timestamp" : { "t" : 1625086457, "i" : 22 } }, "signature" : { "hash" : { "$binary" : "BCifcktqC8uoPcR7ncgMmas8qY8=", "$type" : "00" }, "keyId" : { "$numberLong" : "6930011667187105794" } } } }
at com.mongodb.internal.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:179)
at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:299)
at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:255)
at com.mongodb.internal.connection.UsageTrackingInternalConnection.sendAndReceive(UsageTrackingInternalConnection.java:99)
at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.sendAndReceive(DefaultConnectionPool.java:444)
at com.mongodb.internal.connection.CommandProtocolImpl.execute(CommandProtocolImpl.java:72)
at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:200)
at com.mongodb.internal.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:269)
at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:131)
at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:123)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:242)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:233)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:170)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:163)
at com.mongodb.operation.CreateIndexesOperation$1.call(CreateIndexesOperation.java:175)
at com.mongodb.operation.CreateIndexesOperation$1.call(CreateIndexesOperation.java:170)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:453)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:415)
at com.mongodb.operation.CreateIndexesOperation.execute(CreateIndexesOperation.java:170)
at com.mongodb.operation.CreateIndexesOperation.execute(CreateIndexesOperation.java:70)
at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:193)
at com.mongodb.client.internal.MongoCollectionImpl.executeCreateIndexes(MongoCollectionImpl.java:805)
at com.mongodb.client.internal.MongoCollectionImpl.createIndexes(MongoCollectionImpl.java:788)
at com.mongodb.client.internal.MongoCollectionImpl.createIndexes(MongoCollectionImpl.java:783)
at com.mongodb.client.internal.MongoCollectionImpl.createIndex(MongoCollectionImpl.java:768)
at com.mongodb.client.internal.MongoCollectionImpl.createIndex(MongoCollectionImpl.java:763)
at DatabaseManager.createIndex(DatabaseManager.java:57)
at Main.main(Main.java:23)
Process finished with exit code 1
What can I do to Index the name field here?

ERROR Caused by: com.mongodb.MongoCommandException: Command failed with error 61: query in command must target a single shard key on server

Getting this error "query in command must target a single shard key' on server " while doing collection.count(queryParams);. In Java, how can I read all the data from all the shard/multiple shards? We are using Microsoft Azure Cosmos DB.
[ERROR] Caused by: com.mongodb.MongoCommandException: Command failed with error 61: 'query in command must target a single shard key' on server ".
Sample Code:
MongoCollection<Document> collection = database.getCollection(eventsCollectionName);
Bson queryParams = Filters.and(
Filters.eq("mysystem.name", dmsEvent.getSystem().getName()),
Filters.eq("mysystem.environment", dmsEvent.getSystem().getEnvironment()),
Filters.eq("mymessage.type", dmsEvent.getMessage().getType()),
Filters.eq("myuser.syscode_id", dmsEvent.getUser_id().getSyscode_id()),
Filters.eq("myuser.condition_id", dmsEvent.getUser_id().getCondition_id()));
//This line is erroring out
long recordCount = collection.count(queryParams);
Sample Cosmos DB Collection Document:
Shard key is "/partitionKey".
{
"_id" : ObjectId("5ab85424a43e6b11916ff6c3"),
"myuser" : {
"syscode_id" : 1,
"condition_id" : 1
},
"mysystem" : {
"name" : "4DL",
"environment" : "D"
},
"mymessage" : {
"type" : "A",
"occurance_count" : 1,
"rolltime" : "2018-03-25T18:00Z",
"timestamp" : "2018-03-25T18:00:11.150379Z"
},
"mydata" : {
"count" : "12",
"slot" : [
{
"length" : null,
"value" : "FF00"
}
]
},
"partitionKey" : "18",
"timeToLive" : 777600,
"_ts" : "2018-03-26 02:00:04.495"
}
This got fixed. Count() will not work , have used collection.find(queryParams) and used the shard key to do collection.replaceOne(with the shard key)

MongoTemplate insert status

I want to create a DAO where I save users to my database. They should have unique logins and it's a little problematic as mongo db don't have transactions. I have a class with users that looks like this :
#Document(collection = "users")
public class User {
#Id
private String id;
#Indexed(unique = true)
private String username;
... }
and in my DAO I want to save new user
mongoTemplate.insert(user);
but how can I get the result to send response to my frontend whether user creation was successfull ?
The API will throw org.springframework.dao.DuplicateKeyException when unique index is violated.
Sample Code:-
try {
mongoOperations.insert(order);
} catch (DuplicateKeyException de) {
de.printStackTrace();
}
Exception Message when unique index is violated:-
org.springframework.dao.DuplicateKeyException: { "serverUsed" : "127.0.0.1:27017" , "ok" : 1 , "n" : 0 , "err" : "E11000 duplicate key error collection: localhost.order index: user_1 dup key: { : \"good\" }" , "code" : 11000}; nested exception is com.mongodb.MongoException$DuplicateKey: { "serverUsed" : "127.0.0.1:27017" , "ok" : 1 , "n" : 0 , "err" : "E11000 duplicate key error collection: localhost.order index: user_1 dup key: { : \"good\" }" , "code" : 11000}

MongoDB update element of nested array

I have a mongo collection named firma which has one of the document structure as below:
{
"_id" : ObjectId("5729af099b3ebf1d0ca7ff05"),
"musteriler" : [
{
"_id" : "de0bf813-b707-4a8d-afc2-9752e05c3aa5",
"yetkiliListesi" : [
{
"_id" : "a5e487fa-2034-4817-94f2-3bd837b76284",
"ad" : "Burak",
"soyad" : "Duman 1",
"cepTel" : "3333333333333",
"mail" : "asdf#asdf.com"
},
{
"_class" : "com.bisoft.entity.MusteriYetkili",
"_id" : "bc4b537d-522a-4c9a-9f67-8ca243e18f46",
"ad" : "Ridvan",
"soyad" : "ENİŞ",
"cepTel" : "222222222222",
"mail" : "asdf#asdf.com"
}
]
}
],
"defaultTimezone" : "Europe/Istanbul"
}
In the above json, I need to update element of second array(yetkiliListesi) which _id = "a5e487fa-2034-4817-94f2-3bd837b76284"
Since I am using a java application(using mongo java driver and spring boot MongoTemplate) to access it and execute this query :
mongoTemplate.updateFirst(Query.query(Criteria.where("_id").is("5729af099b3ebf1d0ca7ff05").and("musteriler.yetkiliListesi._id").is("a5e487fa-2034-4817-94f2-3bd837b76284")),
new Update().set("musteriler.yetkiliListesi.$", yetkiliDBO), Firma.class);
In the above query, yetkiliDBO is a BasicDBObject and its content :
yetkiliDBO = {
'_class': 'com.bisoft.entity.MusteriYetkili',
'_id': "a5e487fa-2034-4817-94f2-3bd837b76284",
'ad': 'wer',
'soyad': 'xyz',
'cepTel': "222222222222",
mail: "asdf#asdf.com"
}
when execute my query I have an error
com.mongodb.WriteConcernException: { "serverUsed" : "192.168.2.250:27017" , "ok" : 1 , "n" : 0 , "updatedExisting" : false , "err" : "cannot use the part (musteriler of musteriler.yetkiliListesi.0) to traverse the element
What I need to do?
You can not use the '$' placeholder when traversing nested arrays.
The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value
source
I would suggest restructuring your data into separate, less-nested collections.

Mongodb: Can't save a new element added into BasicDBList

I am trying to add an element to a BasicDBList array and save it back to Mongodb, but when I check the result, it is not written. What did I do wrong? I use java driver version 2.7.2.
DBObject dbObject = coll.findOne(dbQuery);
BasicDBList unreadMsgs = (BasicDBList) dbObject.get("unreadMsgs");
Logger.debug("before incrementing unreadMsgs" + dbObject.toString());
unreadMsgs.add(new BasicDBObject("id", 1).append("unreadMsg", 1));
Logger.debug("after incrementing unreadMsgs : " + dbObject.toString());
coll.save(dbObject);
Logger.debug("check result: " + coll.findOne(dbQuery).toString());
before incrementing unreadMsgs{ "_id" : { "$oid" : "515c5eb88e3278e9c9d55867"} , "unreadMsgs" : [ ]}
after incrementing unreadMsgs : { "_id" : { "$oid" : "515c5eb88e3278e9c9d55867"} , "unreadMsgs" : [ { "id" : 1 , "unreadMsg" : 1}]}
check result: { "_id" : { "$oid" : "515c5eb88e3278e9c9d55867"} , "unreadMsgs" : [ ]}
The problem is that the coll.save(dbObject) is not updating anything.
It works as an insert and, since the _id already exists in the collection, you are getting a duplicateKey exception (you are just not seeing it because of configuration).
You have to use an update, here is how
The save call should work on that case, but I suggest you use an update with $addToSet operation.
Here's the code:
DBObject addToSetObj = BasicDBObjectBuilder.start()
.push("$addToSet")
.push("unreadMsgs")
.add("id", 1)
.add("unreadMsg", 1)
.pop()
.pop()
.get();
// addToSetObj will be { "$addToSet" : { "unreadMsgs" : { "id" : 1 , "unreadMsg" : 1}}}
coll.update(dbQuery, addToSetObj);
Logger.debug("check result: " + coll.findOne(dbQuery).toString());
Any doubts on how to use addToSet, check this out: http://docs.mongodb.org/manual/reference/operator/addToSet/
Thanks for everybody's answer. I found the real problem. It turns out that my collection is capped, and I am not allowed to insert more data into an existing document in a capped collection. I saw the exception after I changed WriteConcern to FSYNC_SAFE. I changed all my collections to uncapped, and the code works now.

Categories