MongoDB: Unique index on array element's property











up vote
19
down vote

favorite
3












I have a structure similar to this:



class Cat {
int id;
List<Kitten> kittens;
}

class Kitten {
int id;
}


I'd like to prevent users from creating a cat with more than one kitten with the same id. I've tried creating an index as follows:



db.Cats.ensureIndex({'id': 1, 'kittens.id': 1}, {unique:true})


But when I attempt to insert a badly-formatted cat, Mongo accepts it.



Am I missing something? can this even be done?










share|improve this question


















  • 1




    See stackoverflow.com/questions/4435637/…
    – pingw33n
    Jul 19 '11 at 8:19















up vote
19
down vote

favorite
3












I have a structure similar to this:



class Cat {
int id;
List<Kitten> kittens;
}

class Kitten {
int id;
}


I'd like to prevent users from creating a cat with more than one kitten with the same id. I've tried creating an index as follows:



db.Cats.ensureIndex({'id': 1, 'kittens.id': 1}, {unique:true})


But when I attempt to insert a badly-formatted cat, Mongo accepts it.



Am I missing something? can this even be done?










share|improve this question


















  • 1




    See stackoverflow.com/questions/4435637/…
    – pingw33n
    Jul 19 '11 at 8:19













up vote
19
down vote

favorite
3









up vote
19
down vote

favorite
3






3





I have a structure similar to this:



class Cat {
int id;
List<Kitten> kittens;
}

class Kitten {
int id;
}


I'd like to prevent users from creating a cat with more than one kitten with the same id. I've tried creating an index as follows:



db.Cats.ensureIndex({'id': 1, 'kittens.id': 1}, {unique:true})


But when I attempt to insert a badly-formatted cat, Mongo accepts it.



Am I missing something? can this even be done?










share|improve this question













I have a structure similar to this:



class Cat {
int id;
List<Kitten> kittens;
}

class Kitten {
int id;
}


I'd like to prevent users from creating a cat with more than one kitten with the same id. I've tried creating an index as follows:



db.Cats.ensureIndex({'id': 1, 'kittens.id': 1}, {unique:true})


But when I attempt to insert a badly-formatted cat, Mongo accepts it.



Am I missing something? can this even be done?







mongodb






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jul 19 '11 at 7:48









Electric Monk

1,32011633




1,32011633








  • 1




    See stackoverflow.com/questions/4435637/…
    – pingw33n
    Jul 19 '11 at 8:19














  • 1




    See stackoverflow.com/questions/4435637/…
    – pingw33n
    Jul 19 '11 at 8:19








1




1




See stackoverflow.com/questions/4435637/…
– pingw33n
Jul 19 '11 at 8:19




See stackoverflow.com/questions/4435637/…
– pingw33n
Jul 19 '11 at 8:19












3 Answers
3






active

oldest

votes

















up vote
27
down vote



accepted










As far as I know, unique indexes only enforce uniqueness across different documents, so this would throw a duplicate key error:



db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )
db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )


But this is allowed:



db.cats.insert( { id: 123, kittens: [ { id: 456 }, { id: 456 } ] } )


I'm not sure if there's any way enforce the constraint you need at the Mongo level, maybe it's something you could check in the application logic when you insert of update?






share|improve this answer

















  • 2




    Unfortunately it seems like you're right - I'll have to enforce this in code. Oh well.
    – Electric Monk
    Jul 19 '11 at 22:36






  • 7




    So sad! :(. There should be an option to ensure uniqueness in document arrays.
    – Juzer Ali
    Aug 3 '12 at 19:06










  • What you can do is write validation hooks when saving in the array to ensure that it is unique
    – Ouwen Huang
    Nov 23 '14 at 7:53


















up vote
23
down vote













Ensuring uniqueness of the individual values in an array field



In addition to the example above, there is a function in MongoDB to ensure that when you are adding a new object/value to an array field, that it will only perform the update if the value/object doesn't already exist.



So if you have a document that looks like this:



{ _id: 123, kittens: [456] }


This would be allowed:



db.cats.update({_id:123}, {$push: {kittens:456}})


resulting in



{ _id: 123, kittens: [456, 456] }


however using the $addToSet function (as opposed to $push) would check if the value already exists before adding it.
So, starting with:



{ _id: 123, kittens: [456] }


then executing:



db.cats.update({_id:123}, {$addToSet: {kittens:456}})


Would not have any effect.



So, long story short, unique constraints don't validate uniqueness within the value items of an array field, just that two documents can't have identical values in the indexed fields.






share|improve this answer




























    up vote
    3
    down vote













    There is an equivalent of insert with uniquness in array attribute. The following command essentially does insert while ensuring the uniqueness of kittens (upsert creates it for you if the object with 123 doesn't already exist).



    db.cats.update(
    { id: 123 },
    { $addToSet: {kittens: { $each: [ 456, 456] }}, $set: {'otherfields': 'extraval', "field2": "value2"}},
    { upsert: true}
    )


    The resulting value of the object will be



    {
    "id": 123,
    "kittens": [456],
    "otherfields": "extraval",
    "field2": "value2"
    }





    share|improve this answer





















    • The important properties are: $addToSet and upsert. The $set property is unrelated to the OP.
      – Michael Cole
      May 23 '17 at 17:23













    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f6743849%2fmongodb-unique-index-on-array-elements-property%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    27
    down vote



    accepted










    As far as I know, unique indexes only enforce uniqueness across different documents, so this would throw a duplicate key error:



    db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )
    db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )


    But this is allowed:



    db.cats.insert( { id: 123, kittens: [ { id: 456 }, { id: 456 } ] } )


    I'm not sure if there's any way enforce the constraint you need at the Mongo level, maybe it's something you could check in the application logic when you insert of update?






    share|improve this answer

















    • 2




      Unfortunately it seems like you're right - I'll have to enforce this in code. Oh well.
      – Electric Monk
      Jul 19 '11 at 22:36






    • 7




      So sad! :(. There should be an option to ensure uniqueness in document arrays.
      – Juzer Ali
      Aug 3 '12 at 19:06










    • What you can do is write validation hooks when saving in the array to ensure that it is unique
      – Ouwen Huang
      Nov 23 '14 at 7:53















    up vote
    27
    down vote



    accepted










    As far as I know, unique indexes only enforce uniqueness across different documents, so this would throw a duplicate key error:



    db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )
    db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )


    But this is allowed:



    db.cats.insert( { id: 123, kittens: [ { id: 456 }, { id: 456 } ] } )


    I'm not sure if there's any way enforce the constraint you need at the Mongo level, maybe it's something you could check in the application logic when you insert of update?






    share|improve this answer

















    • 2




      Unfortunately it seems like you're right - I'll have to enforce this in code. Oh well.
      – Electric Monk
      Jul 19 '11 at 22:36






    • 7




      So sad! :(. There should be an option to ensure uniqueness in document arrays.
      – Juzer Ali
      Aug 3 '12 at 19:06










    • What you can do is write validation hooks when saving in the array to ensure that it is unique
      – Ouwen Huang
      Nov 23 '14 at 7:53













    up vote
    27
    down vote



    accepted







    up vote
    27
    down vote



    accepted






    As far as I know, unique indexes only enforce uniqueness across different documents, so this would throw a duplicate key error:



    db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )
    db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )


    But this is allowed:



    db.cats.insert( { id: 123, kittens: [ { id: 456 }, { id: 456 } ] } )


    I'm not sure if there's any way enforce the constraint you need at the Mongo level, maybe it's something you could check in the application logic when you insert of update?






    share|improve this answer












    As far as I know, unique indexes only enforce uniqueness across different documents, so this would throw a duplicate key error:



    db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )
    db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )


    But this is allowed:



    db.cats.insert( { id: 123, kittens: [ { id: 456 }, { id: 456 } ] } )


    I'm not sure if there's any way enforce the constraint you need at the Mongo level, maybe it's something you could check in the application logic when you insert of update?







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Jul 19 '11 at 8:18









    Chris Fulstow

    30.7k77499




    30.7k77499








    • 2




      Unfortunately it seems like you're right - I'll have to enforce this in code. Oh well.
      – Electric Monk
      Jul 19 '11 at 22:36






    • 7




      So sad! :(. There should be an option to ensure uniqueness in document arrays.
      – Juzer Ali
      Aug 3 '12 at 19:06










    • What you can do is write validation hooks when saving in the array to ensure that it is unique
      – Ouwen Huang
      Nov 23 '14 at 7:53














    • 2




      Unfortunately it seems like you're right - I'll have to enforce this in code. Oh well.
      – Electric Monk
      Jul 19 '11 at 22:36






    • 7




      So sad! :(. There should be an option to ensure uniqueness in document arrays.
      – Juzer Ali
      Aug 3 '12 at 19:06










    • What you can do is write validation hooks when saving in the array to ensure that it is unique
      – Ouwen Huang
      Nov 23 '14 at 7:53








    2




    2




    Unfortunately it seems like you're right - I'll have to enforce this in code. Oh well.
    – Electric Monk
    Jul 19 '11 at 22:36




    Unfortunately it seems like you're right - I'll have to enforce this in code. Oh well.
    – Electric Monk
    Jul 19 '11 at 22:36




    7




    7




    So sad! :(. There should be an option to ensure uniqueness in document arrays.
    – Juzer Ali
    Aug 3 '12 at 19:06




    So sad! :(. There should be an option to ensure uniqueness in document arrays.
    – Juzer Ali
    Aug 3 '12 at 19:06












    What you can do is write validation hooks when saving in the array to ensure that it is unique
    – Ouwen Huang
    Nov 23 '14 at 7:53




    What you can do is write validation hooks when saving in the array to ensure that it is unique
    – Ouwen Huang
    Nov 23 '14 at 7:53












    up vote
    23
    down vote













    Ensuring uniqueness of the individual values in an array field



    In addition to the example above, there is a function in MongoDB to ensure that when you are adding a new object/value to an array field, that it will only perform the update if the value/object doesn't already exist.



    So if you have a document that looks like this:



    { _id: 123, kittens: [456] }


    This would be allowed:



    db.cats.update({_id:123}, {$push: {kittens:456}})


    resulting in



    { _id: 123, kittens: [456, 456] }


    however using the $addToSet function (as opposed to $push) would check if the value already exists before adding it.
    So, starting with:



    { _id: 123, kittens: [456] }


    then executing:



    db.cats.update({_id:123}, {$addToSet: {kittens:456}})


    Would not have any effect.



    So, long story short, unique constraints don't validate uniqueness within the value items of an array field, just that two documents can't have identical values in the indexed fields.






    share|improve this answer

























      up vote
      23
      down vote













      Ensuring uniqueness of the individual values in an array field



      In addition to the example above, there is a function in MongoDB to ensure that when you are adding a new object/value to an array field, that it will only perform the update if the value/object doesn't already exist.



      So if you have a document that looks like this:



      { _id: 123, kittens: [456] }


      This would be allowed:



      db.cats.update({_id:123}, {$push: {kittens:456}})


      resulting in



      { _id: 123, kittens: [456, 456] }


      however using the $addToSet function (as opposed to $push) would check if the value already exists before adding it.
      So, starting with:



      { _id: 123, kittens: [456] }


      then executing:



      db.cats.update({_id:123}, {$addToSet: {kittens:456}})


      Would not have any effect.



      So, long story short, unique constraints don't validate uniqueness within the value items of an array field, just that two documents can't have identical values in the indexed fields.






      share|improve this answer























        up vote
        23
        down vote










        up vote
        23
        down vote









        Ensuring uniqueness of the individual values in an array field



        In addition to the example above, there is a function in MongoDB to ensure that when you are adding a new object/value to an array field, that it will only perform the update if the value/object doesn't already exist.



        So if you have a document that looks like this:



        { _id: 123, kittens: [456] }


        This would be allowed:



        db.cats.update({_id:123}, {$push: {kittens:456}})


        resulting in



        { _id: 123, kittens: [456, 456] }


        however using the $addToSet function (as opposed to $push) would check if the value already exists before adding it.
        So, starting with:



        { _id: 123, kittens: [456] }


        then executing:



        db.cats.update({_id:123}, {$addToSet: {kittens:456}})


        Would not have any effect.



        So, long story short, unique constraints don't validate uniqueness within the value items of an array field, just that two documents can't have identical values in the indexed fields.






        share|improve this answer












        Ensuring uniqueness of the individual values in an array field



        In addition to the example above, there is a function in MongoDB to ensure that when you are adding a new object/value to an array field, that it will only perform the update if the value/object doesn't already exist.



        So if you have a document that looks like this:



        { _id: 123, kittens: [456] }


        This would be allowed:



        db.cats.update({_id:123}, {$push: {kittens:456}})


        resulting in



        { _id: 123, kittens: [456, 456] }


        however using the $addToSet function (as opposed to $push) would check if the value already exists before adding it.
        So, starting with:



        { _id: 123, kittens: [456] }


        then executing:



        db.cats.update({_id:123}, {$addToSet: {kittens:456}})


        Would not have any effect.



        So, long story short, unique constraints don't validate uniqueness within the value items of an array field, just that two documents can't have identical values in the indexed fields.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 17 '13 at 5:14









        doublehelix

        1,3541212




        1,3541212






















            up vote
            3
            down vote













            There is an equivalent of insert with uniquness in array attribute. The following command essentially does insert while ensuring the uniqueness of kittens (upsert creates it for you if the object with 123 doesn't already exist).



            db.cats.update(
            { id: 123 },
            { $addToSet: {kittens: { $each: [ 456, 456] }}, $set: {'otherfields': 'extraval', "field2": "value2"}},
            { upsert: true}
            )


            The resulting value of the object will be



            {
            "id": 123,
            "kittens": [456],
            "otherfields": "extraval",
            "field2": "value2"
            }





            share|improve this answer





















            • The important properties are: $addToSet and upsert. The $set property is unrelated to the OP.
              – Michael Cole
              May 23 '17 at 17:23

















            up vote
            3
            down vote













            There is an equivalent of insert with uniquness in array attribute. The following command essentially does insert while ensuring the uniqueness of kittens (upsert creates it for you if the object with 123 doesn't already exist).



            db.cats.update(
            { id: 123 },
            { $addToSet: {kittens: { $each: [ 456, 456] }}, $set: {'otherfields': 'extraval', "field2": "value2"}},
            { upsert: true}
            )


            The resulting value of the object will be



            {
            "id": 123,
            "kittens": [456],
            "otherfields": "extraval",
            "field2": "value2"
            }





            share|improve this answer





















            • The important properties are: $addToSet and upsert. The $set property is unrelated to the OP.
              – Michael Cole
              May 23 '17 at 17:23















            up vote
            3
            down vote










            up vote
            3
            down vote









            There is an equivalent of insert with uniquness in array attribute. The following command essentially does insert while ensuring the uniqueness of kittens (upsert creates it for you if the object with 123 doesn't already exist).



            db.cats.update(
            { id: 123 },
            { $addToSet: {kittens: { $each: [ 456, 456] }}, $set: {'otherfields': 'extraval', "field2": "value2"}},
            { upsert: true}
            )


            The resulting value of the object will be



            {
            "id": 123,
            "kittens": [456],
            "otherfields": "extraval",
            "field2": "value2"
            }





            share|improve this answer












            There is an equivalent of insert with uniquness in array attribute. The following command essentially does insert while ensuring the uniqueness of kittens (upsert creates it for you if the object with 123 doesn't already exist).



            db.cats.update(
            { id: 123 },
            { $addToSet: {kittens: { $each: [ 456, 456] }}, $set: {'otherfields': 'extraval', "field2": "value2"}},
            { upsert: true}
            )


            The resulting value of the object will be



            {
            "id": 123,
            "kittens": [456],
            "otherfields": "extraval",
            "field2": "value2"
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 17 '16 at 6:18









            timchunght

            17413




            17413












            • The important properties are: $addToSet and upsert. The $set property is unrelated to the OP.
              – Michael Cole
              May 23 '17 at 17:23




















            • The important properties are: $addToSet and upsert. The $set property is unrelated to the OP.
              – Michael Cole
              May 23 '17 at 17:23


















            The important properties are: $addToSet and upsert. The $set property is unrelated to the OP.
            – Michael Cole
            May 23 '17 at 17:23






            The important properties are: $addToSet and upsert. The $set property is unrelated to the OP.
            – Michael Cole
            May 23 '17 at 17:23




















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f6743849%2fmongodb-unique-index-on-array-elements-property%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            404 Error Contact Form 7 ajax form submitting

            How to know if a Active Directory user can login interactively

            TypeError: fit_transform() missing 1 required positional argument: 'X'