2

Below is the schema for an array contacts. The contacts array has a field hashtag which is another array. How do I delete an element openLove from the array Hashtags?

"contacts" : [
    {
        "addedDate" : ISODate("2015-12-02T09:06:09.891Z"),
        "personEmailId" : "tell.fadgfdg@gmail.com",
        "_id" : ObjectId("565eb481bf35eeb83d7f9f13"),
        "verified" : true,
        "favorite" : true,
        "linkedinUserName" : null,
        "facebookUserName" : null,
        "twitterUserName" : "IamlifePaul",
        "count" : 2,
        "relationshipStrength_updated" : 0,
        "contactRelation" : {
            "decisionmaker_influencer" : null,
            "prospect_customer" : "prospect"
        },
        "source" : "abc",
        "mobileNumber" : "3546789",
        "skypeId" : "123",
        "designation" : "test",
        "companyName" : "Something",
        "location" : "Hyderabad, Telangana, India",
        "personName" : "Naveen Paul",
        "personId" : "565022d7dbeaeb9e17fc7083",
        "hashtag" : [

            "latestTag",
            "anotherTag",
            "#hash",
            "openLove",
            "hellTwo",
            "working?",
            "hello",
            "lol",
            "zxc"
        ],
        "lastInteracted" : ISODate("2015-12-08T05:07:53.746Z")
    },
{
        "addedDate" : ISODate("2015-12-02T09:06:09.891Z"),
        "personEmailId" : "naveenpaul.fadgfdg@gmail.com",
        "_id" : ObjectId("565eb481bf35eeb83d7f9f13"),
        "verified" : true,
        "favorite" : true,
        "linkedinUserName" : null,
        "facebookUserName" : null,
        "twitterUserName" : "IamlifePaul",
        "count" : 2,
        "relationshipStrength_updated" : 0,
        "contactRelation" : {
            "decisionmaker_influencer" : null,
            "prospect_customer" : "prospect"
        },
        "source" : "abc",
        "mobileNumber" : "3546789",
        "skypeId" : "123",
        "designation" : "test",
        "companyName" : "Something",
        "location" : "Hyderabad, Telangana, India",
        "personName" : "Naveen Paul",
        "personId" : "565022d7dbeaeb9e17fc7083",
        "hashtag" : [

            "latestTag",
            "anotherTag",
            "#hash",
            "openLove",
            "hellTwo",
            "working?",
            "hello",
            "lol",
            "zxc"
        ],
        "lastInteracted" : ISODate("2015-12-08T05:07:53.746Z")
    },
{
        "addedDate" : ISODate("2015-12-02T09:06:09.891Z"),
        "personEmailId" : "naveenpaul.fadgfdg@gmail.com",
        "_id" : ObjectId("565eb481bf35eeb83d7f9f13"),
        "verified" : true,
        "favorite" : true,
        "linkedinUserName" : null,
        "facebookUserName" : null,
        "twitterUserName" : "IamlifePaul",
        "count" : 2,
        "relationshipStrength_updated" : 0,
        "contactRelation" : {
            "decisionmaker_influencer" : null,
            "prospect_customer" : "prospect"
        },
        "source" : "abc",
        "mobileNumber" : "3546789",
        "skypeId" : "123",
        "designation" : "test",
        "companyName" : "Something",
        "location" : "Hyderabad, Telangana, India",
        "personName" : "Naveen Paul",
        "personId" : "565022d7dbeaeb9e17fc7083",
        "hashtag" : [

            "polly",
            "tagger",
            "#hash",
            "working?",
            "hello",
            "lol",
            "zxc"
        ],
        "lastInteracted" : ISODate("2015-12-08T05:07:53.746Z")
    }

How do I delete an element from the array Hashtags? for example remove openLove?

Naveen Paul
  • 454
  • 8
  • 18
  • Possible duplicate of [How to remove an element from a doubly-nested array in a MongoDB document](http://stackoverflow.com/questions/5228210/how-to-remove-an-element-from-a-doubly-nested-array-in-a-mongodb-document) – thegreenogre Dec 29 '15 at 09:04

3 Answers3

2

You would normally do this using the positional operator $ as follows:

db.collection.update(
    { "contacts.hashtag": "openLove" },
    {
        "$pull": {
            "contacts.$.hashtag": "openLove"
        }
    }
)

However, as this only supports one-level deep arrays (the positional $ operator acts as a placeholder for the first element that matches the query document), only the first element that matches the query document is removed. There is a JIRA trackable for this here: https://jira.mongodb.org/browse/SERVER-831

If you know the index of the hashtags array that has the elememt to be removed beforehand then the update query will be:

db.collection.update(
    { "contacts.hashtag": "openLove" },
    {
        "$pull": {
            "contacts.0.hashtag": "openLove",
            "contacts.1.hashtag": "openLove"
        }
    }
)

Consider redesigning your schema to avoid nested arrays so that you can normalize your collection by creating a separate contacts collection where each document represents a contact, with information common to a set of contacts duplicated in the original collection. Something like the following:

collection schema:

{
    _id: collection_id,
    contacts: [
        ObjectId("565eb481bf35eeb83d7f9f13"), 
        ObjectId("565eb481bf35eeb83d7f9f14"), 
        ObjectId("565eb481bf35eeb83d7f9f15")
    ]
}

contacts schema:

{
    "addedDate" : ISODate("2015-12-02T09:06:09.891Z"),
    "personEmailId" : "tell.fadgfdg@gmail.com",
    "_id" : ObjectId("565eb481bf35eeb83d7f9f13"),
    ...
    "hashtag" : [
        "latestTag",
        "anotherTag",
        "#hash",
        "openLove",
        "hellTwo",
        "working?",
        "hello",
        "lol",
        "zxc"
    ],
    "lastInteracted" : ISODate("2015-12-08T05:07:53.746Z")
},
{
    "addedDate" : ISODate("2015-12-02T09:06:09.891Z"),
    "personEmailId" : "naveenpaul.fadgfdg@gmail.com",
    "_id" : ObjectId("565eb481bf35eeb83d7f9f14"),
    ...
    "hashtag" : [
        "latestTag",
        "anotherTag",
        "#hash",
        "openLove",
        "hellTwo",
        "working?",
        "hello",
        "lol",
        "zxc"
    ],
    "lastInteracted" : ISODate("2015-12-08T05:07:53.746Z")
},
{
    "addedDate" : ISODate("2015-12-02T09:06:09.891Z"),
    "personEmailId" : "naveenpaul.eewsdf@gmail.com",
    "_id" : ObjectId("565eb481bf35eeb83d7f9f15"),
    ...
    "hashtag" : [
        "polly",
        "tagger",
        "#hash",
        "working?",
        "hello",
        "lol",
        "zxc"
    ],
    "lastInteracted" : ISODate("2015-12-08T05:07:53.746Z")
}

Updating the contacts collection would be easier, simply run the operation

db.contacts.update(
    { "hashtag": "openLove" },
    {
        "$pull": { "hashtag": "openLove" }
    }
)

If redesigning the schema is out of your scope then you would need a mechanism to dynamically generate the update document i.e. create the $pull object on the fly. Consider using Map-Reduce to generate that, this answer details the whole operation concept.

Community
  • 1
  • 1
chridam
  • 100,957
  • 23
  • 236
  • 235
2

With the help of chridam's answer, I got it to work by using the object Id of each contact.

db.user.update(
{ "contacts._id": ObjectId("5680f392e623e8b2107e6465") },
{
    "$pull": {
        "contacts.$.hashtag": "openLove"
    }
})
Community
  • 1
  • 1
Naveen Paul
  • 454
  • 8
  • 18
0

This is almost what I need, however the $ positional indicator only matches the FIRST top level array element, and my scenario includes the possibility (just like the OP) that the value we want to remove can occur in multiple index positions.

To remove the value from ALL top level array elements, use this instead:

db.user.update(
{ "contacts._id": ObjectId("5680f392e623e8b2107e6465") },
{
    "$pull": {
        "contacts.$[].hashtag": "openLove"
    }
})
JKH
  • 131
  • 1
  • 8