Reputation:
I have a document schema in Mongodb that looks like this:
{
_id: 1
tags: [{
tag: 'foo'
links: [{
link: 'http:www.google.com'
date: '123'
}]
}]
}
I am trying to push a link into the 'links' array that will be unique to the document.
My first query...
db.userlinks.update (
{_id: 1, tags: {$nin: [{tag:'foo'}]}},
{$push: {'tags': {tag:'foo'}}},
{upsert: true}
)
Gives me this (creates the tag if it doesn't exist)
{ "_id" : 1, "tags" : [ { "tag" : "foo" } ] }
I then follow that up with this query...
db.userlinks.update (
{_id: 1, tags: {tag: 'foo', links: {$nin: [{link: 'http://www.google.com'}]}}},
{$push: {tags: {tag: 'foo', links: {link: 'http://www.google.com', date: '123'}}}},
{upsert: true}
)
But I get this error: "Cannot apply $push/$pushAll modifier to non-array"
I'm pretty sure the problem is in the 'update' component of my second query, but I'm not sure how to fix it. Any help would be appreciated.
My first query is now... (thanks to Joe)
db.userlinks.update (
{_id: 1, tags: {$nin: [{tag:'foo'}]}},
{$push: {'tags': {tag:'foo', links:[]}}},
{upsert: true}
)
My second query is now...
db.userlinks.update (
{_id: 1, 'tags.tag': 'foo'},
{$push: {'tags.$.links': {link: 'http://www.google.com', date: '123'} } }
)
Which successfully pushes the link into the 'links' array, however it also allows duplicates. I can't allow duplicate links. $addToSet kind of works, however if the date changes, then it still inserts a duplicate link.
Is there a way to either check for the existence of the link in the 'query' part of my second query, or instead only addToSet if certain fields match?
Upvotes: 16
Views: 11884
Reputation:
I finally got it... although if anyone can see a better way to do this, please add it as an answer.
// create the userlinks collection if it doesn't exist
// also add a tag 'foo' into it, but only if the tag doesn't exist
db.userlinks.update (
{_id: '1', 'tags.tag': {$nin: ['foo']}},
{$push: {'tags': {tag:'foo', links:[]}}},
{upsert: true}
)
// add a link into the 'foo' tag, but only if the link doesn't exist
db.userlinks.update(
{_id: '1', 'tags.tag': 'foo', 'tags.links.link': {$nin: ['http://foobar.com']}},
{$push: {'tags.$.links': {link: 'http://foobar.com', date: '15'} } }
)
Upvotes: 18
Reputation: 27227
Perhaps change your first query to:
db.userlinks.update (
{_id: 1, tags: {$nin: [{tag:'foo'}]}},
{$push: {'tags': {tag:'foo', links:[]}}},
{upsert: true}
)
The $push operation should only affect links, not the tag.
{$push: {'tags.links': {link: 'http://www.google.com', date: '123'} } },
Upvotes: 1