Schieben Sie Gegenstände über einen Mungo in das Mongo-Array


182

Ich habe SO ein gutes Stück nach der Antwort gesucht, aber ich bin mir sicher, dass ich nicht die richtigen Worte gefunden habe, um zu beschreiben, wonach ich suche.

Grundsätzlich habe ich eine Mongodb-Sammlung namens 'people'. Das Schema für diese Sammlung lautet wie folgt:

people: {
         name: String, 
         friends: [{firstName: String, lastName: String}]
        }

Jetzt habe ich eine sehr einfache Express-Anwendung, die eine Verbindung zur Datenbank herstellt und erfolgreich "Personen" mit einem leeren Freundes-Array erstellt.

An einer sekundären Stelle in der Anwendung befindet sich ein Formular zum Hinzufügen von Freunden. Das Formular enthält Vorname und Nachname sowie POSTs mit dem Namensfeld, um auch auf das richtige Personenobjekt zu verweisen.

Es fällt mir schwer, ein neues Friend-Objekt zu erstellen und es dann in das Friends-Array zu "verschieben".

Ich weiß, dass ich, wenn ich dies über die Mongo-Konsole mache, die Update-Funktion mit $ push als zweites Argument nach den Suchkriterien verwende, aber ich kann anscheinend keinen geeigneten Weg finden, um Mungo dazu zu bringen, dies zu tun.

db.people.update({name: "John"}, {$push: {friends: {firstName: "Harry", lastName: "Potter"}}});

UPDATE: Also war Adrians Antwort sehr hilfreich. Folgendes habe ich getan, um mein Ziel zu erreichen.

In meiner Datei app.js habe ich mithilfe eine temporäre Route festgelegt

app.get('/addfriend', users.addFriend);

wo in meiner Datei users.js habe ich

exports.addFriend = function (req, res, next)
{
var friend = {"firstName": req.body.fName, "lastName": req.body.lName};
Users.findOneAndUpdate({name: req.user.name}, {$push: {friends: friend}});
};

Ich sehe, dass ich möglicherweise collection.findOneAndUpdate () verwenden könnte, bin mir aber nicht sicher, wo ich das implementieren würde? In meinem Modell?
Neurax

Antworten:


280

Vorausgesetzt, var friend = { firstName: 'Harry', lastName: 'Potter' };

Sie haben zwei Möglichkeiten:

Aktualisieren Sie das Modell im Arbeitsspeicher und speichern Sie es (einfaches Javascript array.push):

person.friends.push(friend);
person.save(done);

oder

PersonModel.update(
    { _id: person._id }, 
    { $push: { friends: friend } },
    done
);

Ich versuche immer, die erste Option zu wählen, wenn dies möglich ist, da sie mehr von den Vorteilen des Mungos (Haken, Validierung usw.) berücksichtigt.

Wenn Sie jedoch viele gleichzeitige Schreibvorgänge ausführen, werden Sie auf Rennbedingungen stoßen, bei denen Sie böse Versionsfehler haben, die Sie daran hindern, jedes Mal das gesamte Modell zu ersetzen und den zuvor hinzugefügten Freund zu verlieren. Gehen Sie also nur zu ersteren, wenn es absolut notwendig ist.


1
Ich dachte, die zweite Option wäre tatsächlich die sicherere in Bezug auf den gleichzeitigen Schreibschutz? Haben Sie versehentlich Letzteres gesagt, als Sie Ersteres sagen wollten?
Will Brickner

37
Ja, ich habe gerade überprüft und (im November 2017), es IST sicher die Mungo zu verwenden updateFunktion, während es NICHT IST sicher ein Dokument zu finden, ändern Sie es im Speicher und dann den Anruf .save()auf dem Dokument Methode. Wenn ich sage, dass ein Vorgang "sicher" ist, bedeutet dies, dass selbst wenn eine, zwei oder 50 Änderungen auf ein Dokument angewendet werden, alle erfolgreich angewendet werden und das Verhalten der Aktualisierungen wie erwartet ist. Im Wesentlichen ist die In-Memory-Manipulation unsicher, da Sie möglicherweise an einem veralteten Dokument arbeiten. Beim Speichern gehen also Änderungen verloren, die nach dem Abrufschritt aufgetreten sind.
Will Brickner

2
@ Will Brickner Ein gängiger Workflow dafür ist das Umschließen Ihrer Logik in eine Wiederholungsschleife: (Wiederholbar enthält Abrufen, Ändern, Speichern). Wenn Sie einen VersionError (optimistische Sperrausnahme) zurückerhalten, können Sie diesen Vorgang einige Male wiederholen und jedes Mal eine neue Kopie abrufen. Ich bevorzuge aber immer noch atomare Updates, wenn möglich!
Adrian Schneider

8
@ZackOfAllTrades Hat mich auch verwirrt, aber ich glaube, fertig ist die Rückruffunktion. let done = function(err, result) { // this runs after the mongoose operation }
Benutzer

Wie erhalte ich die ID des Freundobjekts im Rückruf?
Dee Nix

41

Der Operator $ push hängt einen angegebenen Wert an ein Array an.

{ $push: { <field1>: <value1>, ... } }

$ push fügt das Array-Feld mit dem Wert als Element hinzu.

Die obige Antwort erfüllt alle Anforderungen, aber ich habe sie durch die folgenden Schritte zum Laufen gebracht

var objFriends = { fname:"fname",lname:"lname",surname:"surname" };
Friend.findOneAndUpdate(
   { _id: req.body.id }, 
   { $push: { friends: objFriends  } },
  function (error, success) {
        if (error) {
            console.log(error);
        } else {
            console.log(success);
        }
    });
)

Dies ist die, von der ich festgestellt habe, dass sie funktioniert, daher denke ich, dass dies ab 2019 die aktuellste ist. Die beste Antwort, die ich denke, fehlt in irgendeiner Weise und ist möglicherweise unvollständig / veraltet.
Cheesus Toast

Darf ich nur darauf hinweisen, dass Sie möglicherweise einen kleinen Fehler im Code haben. Ich habe es zum Laufen gebracht, weil ich die richtige Variable für mein Projekt eingegeben habe. Wo Sie Friend.findOneAndUpdate () haben Ich denke, es sollte People.findOneAndUpdate () sein. Das würde eher der ursprünglichen Frage entsprechen. Ich könnte es für Sie bearbeiten, aber ich würde es vorziehen, wenn Sie es einfach überprüfen, falls ich falsch liege (ich bin ein wenig neu in Node / Express).
Cheesus Toast

@CheesusToast Ich denke, wenn ich falsch liege, kannst du die Antwort ändern. Ich habe diese Antwort geputtet, die für mich gut funktioniert hat. aber wenn Sie diese Antwort falsch finden, können Sie diese Antwort ändern und ich werde mich freuen, wenn Sie mich korrigieren, Sir :-).
Parth Raval

1
OK, kein Problem, es war sowieso nur eine kleine Bearbeitung. Es ist ein bisschen pingelig von mir, weil die Zuschauer (wie ich) herausgefunden hätten, wohin das Array sowieso verschoben wurde. Ich denke immer noch, dass dies die beste Antwort sein sollte :)
Cheesus Toast

9

Verwenden Sie $pushdiese Option, um das Dokument zu aktualisieren und einen neuen Wert in ein Array einzufügen.

finden:

db.getCollection('noti').find({})

Ergebnis für find:

{
    "_id" : ObjectId("5bc061f05a4c0511a9252e88"),
    "count" : 1.0,
    "color" : "green",
    "icon" : "circle",
    "graph" : [ 
        {
            "date" : ISODate("2018-10-24T08:55:13.331Z"),
            "count" : 2.0
        }
    ],
    "name" : "online visitor",
    "read" : false,
    "date" : ISODate("2018-10-12T08:57:20.853Z"),
    "__v" : 0.0
}

aktualisieren:

db.getCollection('noti').findOneAndUpdate(
   { _id: ObjectId("5bc061f05a4c0511a9252e88") }, 
   { $push: { 
             graph: {
               "date" : ISODate("2018-10-24T08:55:13.331Z"),
               "count" : 3.0
               }  
           } 
   })

Ergebnis für Update:

{
    "_id" : ObjectId("5bc061f05a4c0511a9252e88"),
    "count" : 1.0,
    "color" : "green",
    "icon" : "circle",
    "graph" : [ 
        {
            "date" : ISODate("2018-10-24T08:55:13.331Z"),
            "count" : 2.0
        }, 
        {
            "date" : ISODate("2018-10-24T08:55:13.331Z"),
            "count" : 3.0
        }
    ],
    "name" : "online visitor",
    "read" : false,
    "date" : ISODate("2018-10-12T08:57:20.853Z"),
    "__v" : 0.0
}

2

Eine einfache Möglichkeit, dies zu tun, besteht darin, Folgendes zu verwenden:

var John = people.findOne({name: "John"});
John.friends.push({firstName: "Harry", lastName: "Potter"});
John.save();

0

In meinem Fall habe ich das getan

  const eventId = event.id;
  User.findByIdAndUpdate(id, { $push: { createdEvents: eventId } }).exec();

-3

Ich bin auch auf dieses Problem gestoßen. Meine Lösung bestand darin, ein untergeordnetes Schema zu erstellen. Unten finden Sie ein Beispiel für Ihre Modelle.

---- Personenmodell

const mongoose = require('mongoose');
const SingleFriend = require('./SingleFriend');
const Schema   = mongoose.Schema;

const productSchema = new Schema({
  friends    : [SingleFriend.schema]
});

module.exports = mongoose.model('Person', personSchema);

*** Wichtig: SingleFriend.schema -> Stellen Sie sicher, dass für das Schema Kleinbuchstaben verwendet werden

--- Kinderschema

const mongoose = require('mongoose');
const Schema   = mongoose.Schema;

const SingleFriendSchema = new Schema({
  Name: String
});

module.exports = mongoose.model('SingleFriend', SingleFriendSchema);

Möglicherweise liegt der Grund für die Ablehnung darin, dass dies nicht notwendig erscheint. Parth Ravals Antwort ist völlig ausreichend.
Cheesus Toast
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.