0

Let me start by saying I'm sorry if this has been answered, but I can't get other questions on this site to fit my needs and, more importantly, work.

I have the below example document, with a subdocument of 'address':

{ 
    "_id" : ObjectId("....")
    ,"addresses" : 
        [{
            "start" : ISODate("1973-07-10T00:11:51.111Z")
            ,"value" : "123 long road"
        }] 
}

What I need to do is to close the existing address record with an end attribute, and add a new line for the new address with a new start and value attribute. Eventually, I'll need to do this again so the code needs to update the subdocument record where end does not exist.

The below code does not work, but it's about as far as I can get:

db.sites.update(
      {"_id" : ObjectId("....")
        , "addresses.end" : {"$exists" : false}}
     ,{"$set": {"addresses.$.end" : "fdsa"}});

This gives the error:

Cannot apply the positional operator without a corresponding query field containing an array.

Can anyone point me in the right direction?

JAC2703
  • 423
  • 6
  • 22

3 Answers3

2

Juste replace in your query "addresses.end" : {"$exists" : false} with:

addresses: {$elemMatch: {end: {$exists: false}}}
dgiugg
  • 1,294
  • 14
  • 23
  • Brilliant, the lot of you. Thanks very much :) – JAC2703 Aug 04 '14 at 14:31
  • Guys, it seems that using addresses.$.end in conjunction with $elemMatch only ever updates the first subdocument, and not the one which was a missing end attribute. any ideas how to always update the subdocument that doesn't have an end attribute? – JAC2703 Aug 08 '14 at 16:27
  • It works for me. It updates the first subdocument with a missing `end` attribute... Are you sure you do not have several subdocuments with a missing `end` attribute? – dgiugg Aug 08 '14 at 17:06
  • Got it working too, I had another condition that was never true. Thanks again. – JAC2703 Aug 08 '14 at 18:56
0

I think that the Query should be more specific

**Updated **

db.sites.update ( {"_id" : ObjectId("...."), addresses: { "$elemMatch" : { end:{$exists : false}} } }, {"$set": {"addresses.$.end" : "fdsa"}});

db.sites.find()

results:

{
    "_id" : ObjectId("53df93da560b7815e1237934"),
    "addresses" : [ 
        {
            "start" : ISODate("1973-07-10T00:11:51.111Z"),
            "value" : "123 long road",
            "end" : "fdsa"
        }
    ]
}

but you can update only one

Take a look http://docs.mongodb.org/manual/reference/operator/projection/positional/#proj.S

You can t update more element in Array https://jira.mongodb.org/browse/SERVER-1243

Barno
  • 3,271
  • 5
  • 28
  • 58
  • This is not what the OP is asking: he wants to update the element that does not have and "end" attribute. – dgiugg Aug 04 '14 at 14:18
0

Your address field is poorly defined. you need make it a subdocument or an array of subdocuments. ie { "_id" : ObjectId("....") ,"addresses" : [ { "start" : ISODate("1973-07-10T00:11:51.111Z") ,"value" : "123 long road" } ] }

your query should then work!

Apmis
  • 17
  • 1
  • 1