0

I need to avoid duplications Transactions while inserting the documents in MongoDB database . Getting below exception .The condition is if we try to insert the Key.IdentifierValue with the same value it should throw the duplicate exception but the documents are getting inserted in MongoDB database successfully without any issue. If we remove index options in createIndex method , the document is getting inserted but duplicate transactions are happening and not able to do with upsert operation .Any help will be appreciated

Document Structure:

"_id" : ObjectId("12345678"), 
"Key": {
      "color": "red",
      },
    
      "IdentifierValure": "Sample.txt",
    
  Command failed with error 67 (CannotCreateIndex): 'Index build failed: 48888886ee5e3: Collection sample ( 48888886ee5e3-0788-4414-bc43-2e118e79246e ) :: caused by :: cannot create unique index over { Key.IdentifierValue:: -1 } with shard key pattern { _id: "hashed" }'

    @ResponseBody
            public boolean createSample(@Valid @RequestBody Document... sample) {
                MongoDatabase database = this.mongoClient.getDatabase("database");
                MongoCollection<Document> collection = database.getCollection("Sample");
                  
                 List<Document> documentList = new ArrayList<>(sample.length);
                 IndexOptions indexOptions = new IndexOptions().unique(true);
          
            String resultCreateIndex = collection.createIndex(Indexes.descending("Key.IdentifierValue"), indexOptions);
                for (Document doc : sample) {
                    documentList.add(Document.parse(doc.toJson()));
                }
                collection.insertMany(documentList);
        
                return sucessfully inserted;
            }
      
    
        
Rose
  • 89
  • 5
  • 18
  • The error message you are getting here is a failure to create the index. Creating the index isn't something that is typically done by the application while it is running. Check what the existing index is (`db.getSiblingDB('database').sample.getIndexes()`), remove the index on `"Key.IdentifierValue"` (assuming it is not `unique`), and create it as `unique`. You will need to remove any existing documents in the collection that are duplicates before building the index. – user20042973 Nov 29 '22 at 18:29
  • @user20042973 , thank you for the quick response, but the index is required for the other service as our services are base done on micro service architecture. Is it not possible to remove the index as it is required by other services. Could you please help how to implement in that case – Rose Nov 30 '22 at 07:36
  • Tried to remove the index but still it is giving the same exception – Rose Nov 30 '22 at 13:28

1 Answers1

1

I was attempting to write an answer that expanded on my comments and addressed your original question/error message. It looks like you have just edited your post to meaningfully change the question. Please ask a different question next time instead.


Original Problem

There are probably a few problems here, but the central one is that you currently do not seem to have a unique index on the Key.IdentifierValue field.

Reformatted, the full error that you are receiving is:

com.mongodb.MongoCommandException: Command failed with error 86 (IndexKeySpecsConflict): 
  An existing index has the same name as the requested index. 
  When index names are not specified, they are auto generated and can cause conflicts. 
  Please refer to our documentation. 
  Requested index: { v: 2, unique: true, key: { Key.IdentifierValue: 1 }, name: "Key.IdentifierValue: 1" }, 
  existing index: { v: 2, key: { Key.IdentifierValue: 1}, name: "Sample.Service_1" }

More specifically, there is already an index present in the collection (second definition below) which conflicts with the one that the code is trying to create (first definition below). Formatted further for easy comparison:

{ v: 2, unique: true, key: { Key.IdentifierValue: 1 }, name: "Key.IdentifierValue: 1" } 
{ v: 2,               key: { Key.IdentifierValue: 1 }, name: "Sample.Service_1" }

In order to create your unique index, you will need to drop the existing one first:

> //First attempt fails because of the existing index
>  db.sample.createIndex({ "Key.IdentifierValue": 1 },{name: "Key.IdentifierValue: 1", unique: true})
{
    "ok" : 0,
    "errmsg" : "Index: { v: 2, unique: true, key: { Key.IdentifierValue: 1.0 }, name: \"Key.IdentifierValue: 1\", ns: \"test.sample\" } already exists with different options: { v: 2, key: { Key.IdentifierValue: 1.0 }, name: \"Sample.Service_1\", ns: \"test.sample\" }",
    "code" : 85,
    "codeName" : "IndexOptionsConflict"
}
>
> //Drop the conflicting index that is present
> db.sample.dropIndex({ "Key.IdentifierValue": 1 })
{ "nIndexesWas" : 2, "ok" : 1 }
>
> //Index can now be created successfully
> db.sample.createIndex({ "Key.IdentifierValue": 1 },{name: "Key.IdentifierValue: 1", unique: true})
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

Newer versions of MongoDB behave differently. You can create the unique index without dropping the existing one first:

> db.version()
6.0.1
test> db.sample.getIndexes()
[
  { v: 2, key: { _id: 1 }, name: '_id_' },
  { v: 2, key: { 'Key.IdentifierValue': 1 }, name: 'Sample.Service_1' },
  { v: 2, key: { 'Key.IdentifierValue': 1 }, name: 'Key.IdentifierValue: 1', unique: true }
]

Furthermore, you can also convert an existing non-unique index to be unique as mentioned here


New Problem

After editing your question, the new (different) error is:

Command failed with error 67 (CannotCreateIndex): 
  'Index build failed: 48888886ee5e3: 
  Collection sample ( 48888886ee5e3-0788-4414-bc43-2e118e79246e ) :: caused by :: 
  cannot create unique index over { Key.IdentifierValue:: -1 } with shard key pattern { _id: "hashed" }'

Apparently you have a sharded collection which is using the hashed value of _id as the shard key. The ability to enforce uniqueness in sharded clusters is documented here. Borrowing some text from there:

MongoDB can enforce a uniqueness constraint on a ranged shard key index. Through the use of a unique index on the shard key

...

  • For an already-sharded collection, you cannot create unique indexes on other fields.

...

You cannot specify a unique constraint on a hashed index.

Based on that last line there, you will not be able to create the unique index that you want based on your current shard key. You will have to choose a different shard key per the linked documentation if you wish to enforce uniqueness on a sharded collection.


General Comment

It is not the responsibility of the application to create indexes directly. Having the code attempt to do so on every write adds unnecessary overhead and should be avoided.

Instead, you should create and manage your indexes separately outside of the code.

user20042973
  • 4,096
  • 2
  • 3
  • 14
  • Thank you for the detailed explanation . Actually Indexes already created directly in database . What I need to do exactly that duplicate transactions will not processed while inserting the documents based on field in mongodb database .So I am trying to create the index to avoid the duplicate transactions based on field but that is happening .Is there any other way to avoid the duplicate transactions with mongoDB Java driver – Rose Nov 30 '22 at 15:21
  • And more over I have tried to drop the index and created the index that is also failing with the error – Rose Nov 30 '22 at 15:21
  • I don't think you have had a `unique` index at any point. Originally you were unable to create it because of the conflicting (non-unique) index on the same field. More recently it seems you can not create it because the collection is shared on a different field. Without the unique index being present the database can't enforce uniqueness. Attempting to enforce uniqueness in the application will likely be difficult and/or unscalable to do. – user20042973 Nov 30 '22 at 15:34
  • Thank you for your suggestion . Is there any other way to avoid the duplicate transactions with mongo-java-driver while inserting the documents in mongodb database – Rose Nov 30 '22 at 16:49
  • There may be. But it is not something that is answerable in a comment and would definitely deserve its own question. To reiterate my word of caution though - such an approach would be a lot more work, probably not perform as well, and greatly introduce the opportunity for problems/bugs to occur. I'd certainly recommend designing your database so that you can use a `unique` index to do the heavy lifting of enforcing uniqueness. – user20042973 Nov 30 '22 at 17:02