2013-04-14 14 views
16

Ich habe ein Dokument Schema in MongoDB, die wie folgt aussieht:aktualisiert Multi verschachtelter Array in MongoDB

{ 
    _id: 1 
    tags: [{ 
     tag: 'foo' 
     links: [{ 
      link: 'http:www.google.com' 
      date: '123' 
     }] 
    }] 
} 

Ich versuche, einen Link in das ‚Links‘ Array zu drücken, die das Dokument eindeutig sein wird.

Meine erste Abfrage ...

db.userlinks.update (
    {_id: 1, tags: {$nin: [{tag:'foo'}]}}, 
    {$push: {'tags': {tag:'foo'}}}, 
    {upsert: true} 
) 

gibt mir diese (erstellt den Tag, wenn sie nicht existiert)

{ "_id" : 1, "tags" : [ { "tag" : "foo" } ] } 

ich dann, dass mit dieser Abfrage folgen ...

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} 
) 

Aber ich bekomme diese Fehlermeldung:

"Can not $ Push/$ pushAll Modifikator auf nicht-Array-Anwendung"

Ich bin mir ziemlich sicher, dass das Problem in der 'Update' Komponente meiner zweiten Abfrage ist, aber ich bin mir nicht sicher, wie ich es beheben soll. Jede Hilfe wäre willkommen.

EDIT

Meine erste Frage ist jetzt ... (dank Joe)

db.userlinks.update (
    {_id: 1, tags: {$nin: [{tag:'foo'}]}}, 
    {$push: {'tags': {tag:'foo', links:[]}}}, 
    {upsert: true} 
) 

Meine zweite Frage ist jetzt ...

db.userlinks.update (
    {_id: 1, 'tags.tag': 'foo'}, 
    {$push: {'tags.$.links': {link: 'http://www.google.com', date: '123'} } } 
) 

, die erfolgreich den Link drückt in das Array 'Links', erlaubt jedoch auch Duplikate. Ich kann keine doppelten Links zulassen. $ addToSet Art von Arbeiten, jedoch wenn das Datum sich ändert, fügt es immer noch eine doppelte Verknüpfung ein.

Gibt es eine Möglichkeit, entweder die Existenz des Links im 'query' Teil meiner zweiten Abfrage zu überprüfen, oder stattdessen nur addToSet, wenn bestimmte Felder übereinstimmen?

+0

können Sie nicht. Überlegen Sie, Ihr Schema zu ändern? –

+3

Ich möchte nicht besonders mein Schema ändern, weil dies genau so modelliert ist, wie es ausgegeben wird, was bedeutet, dass ich keine Daten verwirren muss, sobald ich es aus der db herausgeholt habe. Ich dachte, das sollte der Hauptgrund sein, Mongodb tatsächlich zu benutzen? Die Fähigkeit, Ihre Objekte direkt in die Datenbank und aus dieser heraus zu modellieren. –

Antwort

18

Ich habe es endlich ... obwohl, wenn jemand einen besseren Weg sehen kann, dies zu tun, fügen Sie es bitte als Antwort hinzu.

// 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'} } } 
) 
+1

Interessant. Danke für das Update. Fühlen Sie sich frei, Ihre eigene Antwort als akzeptiert zu markieren. –

+0

@Harley: Wie können wir das Datum auf 20 aktualisieren, wenn wir die _id, "tags.tags" und "tags.links.link" kennen ... db.doc.update ({_ id:, 'tags.tags:,' tags.links.link ':}, {$ inc: {' tags.links. $. date ': 20}}) funktioniert nicht, da wir zwei Arrays haben ... Bitte Hilfe –

+0

Sorry Praveen, mit dem ich nicht gearbeitet habe Mongo, seit ich diesen Post gemacht habe und ich habe im Grunde die Feinheiten der Abfragesprache vergessen, fürchte ich. Vielleicht eine neue Frage eröffnen? –

1

Vielleicht ist Ihre erste Abfrage ändern:

db.userlinks.update (
    {_id: 1, tags: {$nin: [{tag:'foo'}]}}, 
    {$push: {'tags': {tag:'foo', links:[]}}}, 
    {upsert: true} 
) 

Die $ Push-Betrieb sollte nur Links beeinflussen, nicht den Tag.

+0

Das initiierte die 'Links' zu einem leeren Array, was gut ist und wahrscheinlich etwas, das ich brauchte, aber meine zweite Abfrage löst immer noch denselben Fehler aus. –

+0

Die Antwort wurde aktualisiert. –

+0

Leider habe ich immer noch den gleichen Fehler bei der Verwendung dieser als zweite Abfrage: db.userlinks.update ( {_id: 1, Tags: {tag: 'foo', Links: {$ nin: [{link: 'google. com '}]}}}, {$ push: {' tags.links ': {link:' google.com ', Datum:' 123 '}}}, {upsert: true} ) –