Dorong item ke array luong melalui luwak


185

Saya sudah mencari-cari jawaban yang baik, tetapi saya yakin saya kehilangan kata-kata yang tepat untuk menggambarkan apa yang saya cari.

Pada dasarnya saya memiliki koleksi mongodb yang disebut 'orang'. Skema untuk koleksi itu adalah sebagai berikut:

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

Sekarang, saya memiliki aplikasi ekspres yang sangat mendasar yang terhubung ke database dan berhasil membuat 'orang' dengan array teman kosong.

Di tempat kedua dalam aplikasi, formulir ada di tempat untuk menambah teman. Formulir mengambil firstName dan lastName dan kemudian POST dengan bidang nama juga untuk referensi ke objek orang yang tepat.

Apa yang saya kesulitan lakukan adalah membuat objek teman baru dan kemudian "mendorong" ke dalam array teman.

Saya tahu bahwa ketika saya melakukan ini melalui konsol luwak saya menggunakan fungsi pembaruan dengan $ push sebagai argumen kedua saya setelah kriteria pencarian, tetapi saya tidak bisa menemukan cara yang tepat untuk mendapatkan luwak untuk melakukan ini.

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

UPDATE: Jadi, jawaban Adrian sangat membantu. Berikut ini adalah apa yang saya lakukan untuk mencapai tujuan saya.

dalam file app.js saya, saya menetapkan rute sementara menggunakan

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

di mana di file users.js saya miliki

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

Saya melihat bahwa saya berpotensi menggunakan collections.findOneAndUpdate (), tetapi saya tidak yakin di mana saya akan mengimplementasikannya? Dalam model saya?
Neurax

Jawaban:


282

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

Ada dua opsi yang Anda miliki:

Perbarui model dalam memori, dan simpan (plain javascript array.push):

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

atau

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

Saya selalu mencoba dan mencari opsi pertama jika memungkinkan, karena itu akan lebih menghargai manfaat yang diberikan luwak (kait, validasi, dll.).

Namun, jika Anda melakukan banyak penulisan bersamaan, Anda akan mendapatkan kondisi balapan di mana Anda akan berakhir dengan kesalahan versi yang buruk untuk menghentikan Anda mengganti seluruh model setiap kali dan kehilangan teman sebelumnya yang Anda tambahkan. Jadi hanya pergi ke yang pertama ketika itu benar-benar diperlukan.


1
Saya pikir opsi kedua sebenarnya yang lebih aman dalam hal perlindungan penulisan bersamaan? Apakah Anda secara tidak sengaja mengatakan yang terakhir ketika Anda bermaksud mengatakan yang pertama?
Will Brickner

37
Yap, saya hanya diperiksa dan (dalam Nov 2017), itu IS aman untuk menggunakan luwak updatefungsi, sementara itu TIDAK aman untuk menemukan dokumen, memodifikasi dalam memori, dan kemudian memanggil .save()metode pada dokumen. Ketika saya mengatakan bahwa operasi itu 'aman', itu berarti bahwa bahkan jika satu, dua, atau 50 perubahan diterapkan ke dokumen, mereka semua akan berhasil diterapkan dan perilaku pembaruan akan seperti yang Anda harapkan. Pada dasarnya manipulasi di dalam memori tidak aman karena Anda bisa mengerjakan dokumen yang sudah usang sehingga saat Anda menyimpan, perubahan yang terjadi setelah langkah pengambilan hilang.
Will Brickner

2
@Will Brickner alur kerja umum untuk itu adalah untuk membungkus logika Anda dalam loop coba lagi: (retryable berisi fetch, modifikasi, save) Jika Anda mendapatkan kembali VersionError (pengecualian kunci optimis), Anda dapat mencoba kembali operasi itu beberapa kali dan mengambil salinan baru setiap kali. Saya masih lebih suka pembaruan atom jika memungkinkan!
Adrian Schneider

8
@ZackOfAllTrades Bingung juga, tapi saya yakin yang dilakukan adalah fungsi callback. let done = function(err, result) { // this runs after the mongoose operation }
pengguna

bagaimana cara mendapatkan id objek teman di callback?
Dee Nix

41

Operator $ push menambahkan nilai yang ditentukan ke array.

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

$ push menambahkan bidang array dengan nilai sebagai elemennya.

Jawaban di atas memenuhi semua persyaratan, tetapi saya membuatnya bekerja dengan melakukan hal berikut

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

Ini adalah salah satu yang saya temukan untuk bekerja, jadi saya pikir ini adalah yang paling up to date pada 2019. Salah satu jawaban terbaik yang saya pikir kurang dalam beberapa cara dan mungkin tidak lengkap / ketinggalan zaman.
Cheesus Toast

Bolehkah saya menunjukkan bahwa Anda mungkin memiliki sedikit kesalahan dalam kode. Saya mulai bekerja karena saya memasukkan variabel yang benar untuk proyek saya. Di mana Anda memiliki Friend.findOneAndUpdate () saya pikir itu harus People.findOneAndUpdate (). Itu akan lebih sesuai dengan pertanyaan awal. Saya bisa mengeditnya untuk Anda, tetapi saya lebih suka Anda mengeceknya kalau-kalau saya salah (saya sedikit baru dengan node / express).
Cheesus Toast

@ JesusToast Saya pikir, jika saya salah, Anda dapat mengubah jawabannya. Saya telah meletakkan jawaban ini yang berfungsi dengan baik untuk saya. tetapi jika Anda menemukan jawaban ini salah, Anda dapat mengubah jawaban ini & saya akan senang jika Anda memperbaiki saya Pak :-).
Parth Raval

1
OK, tidak masalah, itu hanya edit kecil saja. Ini agak pilih-pilih saya karena pemirsa (seperti saya) akan bekerja di mana array didorong ke toh. Saya masih berpikir ini harus menjadi jawaban terbaik :)
Cheesus Toast

10

Gunakan $pushuntuk memperbarui dokumen dan memasukkan nilai baru di dalam array.

Temukan:

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

hasil untuk menemukan:

{
    "_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
}

memperbarui:

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

hasil untuk pembaruan:

{
    "_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

Cara mudah untuk melakukannya adalah dengan menggunakan yang berikut:

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

0

Dalam kasus saya, saya melakukan ini

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

-3

Saya mengalami masalah ini juga. Perbaikan saya adalah membuat skema anak. Lihat di bawah untuk contoh model Anda.

---- Model orang

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

*** Penting: SingleFriend.schema -> pastikan untuk menggunakan huruf kecil untuk skema

--- Skema anak

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

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

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

Mungkin alasan untuk downvote adalah karena ini sepertinya tidak perlu. Jawaban Parth Raval cukup memadai.
Cheesus Toast
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.