6

I have the model like following

@CompoundIndexes(value = {
        @CompoundIndex(name = "catalog_idx", def = "{'code' : 1, 'brand' : 1}", unique = true) })
@Document(collection = Catalog.ENTITY)
public class Catalog extends AbstractModel<String> {

    private static final long serialVersionUID = 1L;

    public static final String ENTITY = "catalog";

    @NotNull(message = "Code is required")
    @Field("code")
    private String code;

    @NotNull(message = "Brand is required")
    @DBRef(lazy = true)
    @Field("brand")
    private Brand brand;
}

When i do save with mongoTemplate.save(object); i see only 2 objects created in DB instead of 6. Just before save my debug lines for objects to be saved.

Catalog [code=StagedCatalog, brand=Brand [code=Brand_3]]
Catalog [code=StagedCatalog, brand=Brand [code=Brand_2]]
Catalog [code=StagedCatalog, brand=Brand [code=Brand_1]]
Catalog [code=OnlineCatalog, brand=Brand [code=Brand_2]]
Catalog [code=OnlineCatalog, brand=Brand [code=Brand_1]]
Catalog [code=OnlineCatalog, brand=Brand [code=Brand_3]]

Any ideas why ? I feel the Index unique thing is not working somehow. I want code and brand to be unique combination.

public abstract class AbstractModel<ID extends Serializable> implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    private ID id;
}
Saurabh Kumar
  • 16,353
  • 49
  • 133
  • 212

2 Answers2

5

You have set a unique index. It means that you will be unable to have 2 documents with the same code and brand.

Now you have set the ID column to ID object. The fact that you have 2 insert instead of 6 means that you use the same ID for 3 insert, something like :

for (code: {"StagedCatalog","OnlineCatalog"} ) {
    ID id=new ID(...);
    for (brand: {1, 2, 3}){
        Catalog cat=new Catalog();
        cat.setId(id);              // <<== this is wrong, you reuse the same id, you will insert first brand, then update to brand2 and brand3.
        cat.setCode(code);
        cat.setBrand(brand);
        mongoTemplate.persist(cat);
    }
}

To prevent that, you need to:

Catalog cat=new Catalog();
ID id=new ID(realUniqueId);  // RealuniqueId can be code+brand for instance
cat.setId(id); 
...
wargre
  • 4,575
  • 1
  • 19
  • 35
  • ID is set by spring mongodb directly. – Saurabh Kumar Aug 11 '17 at 08:30
  • You sure your don't reuse the same object ? – wargre Aug 11 '17 at 08:47
  • Yes i am sure. You see the logs just before i do save. Now none of the code and brand combination are colliding. What i understood from compound keys as per spring documentation I hope my config is correct Additionally when i do save all these objects are fresh that means there ID is empty value before save and after save they will have a value. So i dont understand why spring mongodb is saving withing the existing entity. So spring mongodb compound key unique i assume the combination is unique and not individual code and brand are unique. – Saurabh Kumar Aug 11 '17 at 09:01
  • Check this https://stackoverflow.com/questions/7222062/mongodb-composite-key . So according to your posting i assume you are negating the spring documentation. – Saurabh Kumar Aug 11 '17 at 09:06
  • The log show that the content of object change, not that the object is unique or not. It is why I'd like you to log the id column. It will show that id is duplicate (it is the only possibility). @CompoundIndexes is not a primary key, only the id index is primary. if you insert {id: 1, code:Staged, brand: A} then you try to push {id:1, code: Online, brand: B} it is the same object, it will update the object 1. Your index will be ok, because first step, there is only on object with (Staged, A), second step, the (Staged, A) is removed from index, (Online, B) is added, which is also unique. – wargre Aug 11 '17 at 09:19
0

db.collection.save()

Updates an existing document or inserts a new document, depending on its document parameter.

Document Structure

Kondal
  • 2,870
  • 5
  • 26
  • 40