Cara mendefinisikan objek dalam array dalam skema Mongoose dengan benar dengan indeks geo 2d

113

Saat ini saya mengalami masalah dalam membuat skema untuk dokumen di bawah ini. Respons dari server selalu mengembalikan nilai bidang "trk" sebagai [Objek]. Entah bagaimana saya tidak tahu bagaimana ini harus bekerja, karena saya mencoba setidaknya semua pendekatan yang masuk akal bagi saya ;-)

Jika ini membantu, versi Mongoose saya adalah 3.6.20 dan MongoDB 2.4.7 Dan sebelum saya lupa, alangkah baiknya juga mengaturnya sebagai Index (2d)

Data asli:

{
    "_id": ObjectId("51ec4ac3eb7f7c701b000000"),
    "gpx": {
        "metadata": {
            "desc": "Nürburgring VLN-Variante",
            "country": "de",
            "isActive": true
        },
    "trk": [
    {
        "lat": 50.3299594,
        "lng": 6.9393006
    },
    {
        "lat": 50.3295046,
        "lng": 6.9390688
    },
    {
        "lat": 50.3293714,
        "lng": 6.9389939
    },
    {
        "lat": 50.3293284,
        "lng": 6.9389634
    }]
    }
}

Skema Mongoose:

var TrackSchema = Schema({
            _id: Schema.ObjectId,
            gpx: {
                metadata: {
                    desc: String,
                    country: String,
                    isActive: Boolean
                },
                trk: [{lat:Number, lng:Number}]
            }
        }, { collection: "tracks" });

Tanggapan dari tab Jaringan di Chrome selalu terlihat seperti ini (itu hanya bagian trk yang salah):

{ trk: 
      [ [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],

Saya sudah mencoba definisi Skema yang berbeda untuk "trk":

  1. trk: Schema.Types.Mixed
  2. trk: [Schema.Types.Mixed]
  3. trk: [{jenis: [Angka], indeks: "2d"}]

Harap Anda dapat membantu saya ;-)

niels_h
sumber

Jawaban:

219

Anda dapat mendeklarasikan trk dengan cara berikut: - baik

trk : [{
    lat : String,
    lng : String
     }]

atau

trk : { type : Array , "default" : [] }

Dalam kasus kedua selama penyisipan buat objek dan dorong ke dalam array seperti

db.update({'Searching criteria goes here'},
{
 $push : {
    trk :  {
             "lat": 50.3293714,
             "lng": 6.9389939
           } //inserted data is the object to be inserted 
  }
});

atau Anda dapat mengatur Array objek dengan

db.update ({'seraching criteria goes here ' },
{
 $set : {
          trk : [ {
                     "lat": 50.3293714,
                     "lng": 6.9389939
                  },
                  {
                     "lat": 50.3293284,
                     "lng": 6.9389634
                  }
               ]//'inserted Array containing the list of object'
      }
});
Kundu
sumber
ada ide bagaimana memberi nama bidang html dalam kasus seperti itu misalnya jika kita perlu menyimpan array objek javascript dalam database? Misalnya, penamaan bidang sebagai trk.latdan trk.lngdi html tidak akan berfungsi.
Raeesaa
3
trk: {type: Array, "default": []} paling cocok untuk saya! Sederhana dan elegan!
spiral
1
@DpGeek jika Anda mendeklarasikan array dalam format itu, Anda tidak dapat memperbarui bidang array secara langsung. Untuk memperbarui array secara langsung saya menggunakan subschema {lat: String, lng: String}. Jika Anda tidak menginginkan fasilitas itu maka trk: {type: Array, "default": []} akan menjadi yang terbaik jika tidak, Anda harus mendeklarasikan subschema.
Kundu
default tanpa tanda kutip bekerja untuk sayatrk : { type : Array , default : ['item1', 'item2'] }
Shardul
1
apakah itu masih akan berfungsi jika bidang 'lat' dan 'lng' di mana didefinisikan sebagai Nomor, bukan string?
jimijazz
63

Saya memiliki masalah yang sama dengan luwak:

fields: 
    [ '[object Object]',
     '[object Object]',
     '[object Object]',
     '[object Object]' ] }

Sebenarnya, saya menggunakan "type" sebagai nama properti di skema saya:

fields: [
    {
      name: String,
      type: {
        type: String
      },
      registrationEnabled: Boolean,
      checkinEnabled: Boolean
    }
  ]

Untuk menghindari perilaku itu, Anda harus mengubah parameter menjadi:

fields: [
    {
      name: String,
      type: {
        type: { type: String }
      },
      registrationEnabled: Boolean,
      checkinEnabled: Boolean
    }
  ]
Pierre Maoui
sumber
4
ya, bahkan tidak berpikir tentang itu. Itu menyelesaikan masalah saya tepat sebelum saya mulai membanting barang-barang di meja saya haha ​​terima kasih lagi. Saya hanya akan menghindari 'mengetik' dalam skema luwak saya mulai sekarang.
blackops
Dapatkah Anda memberikan contoh json yang coba Anda masukkan?
owensmartin
1
atau Anda bisa meneruskan opsi typeKey ke pembuat skema Anda untuk menimpa deklarasi tipe
jimijazz
2

Terima kasih atas balasannya.

Saya mencoba pendekatan pertama, tetapi tidak ada yang berubah. Kemudian, saya mencoba mencatat hasilnya. Saya hanya mengebor level demi level, hingga akhirnya saya sampai di tempat data ditampilkan.

Setelah beberapa saat saya menemukan masalah: Ketika saya mengirim respon, saya mengubahnya menjadi string melalui .toString().

Saya memperbaikinya dan sekarang berfungsi dengan sangat baik. Maaf atas alarm palsu.

niels_h
sumber
1

Masalah yang perlu saya selesaikan adalah menyimpan kontrak yang berisi beberapa bidang (alamat, buku, jumlah_hari, peminjam_addr, blk_data), blk_data adalah daftar transaksi (nomor blok dan alamat transaksi). Pertanyaan dan jawaban ini membantu saya. Saya ingin membagikan kode saya seperti di bawah ini. Semoga ini membantu.

  1. Definisi skema. Lihat blk_data.
var ContractSchema = new Schema(
    {
        address: {type: String, required: true, max: 100},  //contract address
        // book_id: {type: String, required: true, max: 100},  //book id in the book collection
        book: { type: Schema.ObjectId, ref: 'clc_books', required: true }, // Reference to the associated book.
        num_of_days: {type: Number, required: true, min: 1},
        borrower_addr: {type: String, required: true, max: 100},
        // status: {type: String, enum: ['available', 'Created', 'Locked', 'Inactive'], default:'Created'},

        blk_data: [{
            tx_addr: {type: String, max: 100}, // to do: change to a list
            block_number: {type: String, max: 100}, // to do: change to a list
        }]
    }
);
  1. Buat catatan untuk koleksi di MongoDB. Lihat blk_data.
// Post submit a smart contract proposal to borrowing a specific book.
exports.ctr_contract_propose_post = [

    // Validate fields
    body('book_id', 'book_id must not be empty.').isLength({ min: 1 }).trim(),
    body('req_addr', 'req_addr must not be empty.').isLength({ min: 1 }).trim(),
    body('new_contract_addr', 'contract_addr must not be empty.').isLength({ min: 1 }).trim(),
    body('tx_addr', 'tx_addr must not be empty.').isLength({ min: 1 }).trim(),
    body('block_number', 'block_number must not be empty.').isLength({ min: 1 }).trim(),
    body('num_of_days', 'num_of_days must not be empty.').isLength({ min: 1 }).trim(),

    // Sanitize fields.
    sanitizeBody('*').escape(),
    // Process request after validation and sanitization.
    (req, res, next) => {

        // Extract the validation errors from a request.
        const errors = validationResult(req);
        if (!errors.isEmpty()) {
            // There are errors. Render form again with sanitized values/error messages.
            res.status(400).send({ errors: errors.array() });
            return;
        }

        // Create a Book object with escaped/trimmed data and old id.
        var book_fields =
            {
                _id: req.body.book_id, // This is required, or a new ID will be assigned!
                cur_contract: req.body.new_contract_addr,
                status: 'await_approval'
            };

        async.parallel({
            //call the function get book model
            books: function(callback) {
                Book.findByIdAndUpdate(req.body.book_id, book_fields, {}).exec(callback);
            },
        }, function(error, results) {
            if (error) {
                res.status(400).send({ errors: errors.array() });
                return;
            }

            if (results.books.isNew) {
                // res.render('pg_error', {
                //     title: 'Proposing a smart contract to borrow the book',
                //     c: errors.array()
                // });
                res.status(400).send({ errors: errors.array() });
                return;
            }

            var contract = new Contract(
                {
                    address: req.body.new_contract_addr,
                    book: req.body.book_id,
                    num_of_days: req.body.num_of_days,
                    borrower_addr: req.body.req_addr

                });

            var blk_data = {
                    tx_addr: req.body.tx_addr,
                    block_number: req.body.block_number
                };
            contract.blk_data.push(blk_data);

            // Data from form is valid. Save book.
            contract.save(function (err) {
                if (err) { return next(err); }
                // Successful - redirect to new book record.
                resObj = {
                    "res": contract.url
                };
                res.status(200).send(JSON.stringify(resObj));
                // res.redirect();
            });

        });

    },
];
  1. Perbarui catatan. Lihat blk_data.
// Post lender accept borrow proposal.
exports.ctr_contract_propose_accept_post = [

    // Validate fields
    body('book_id', 'book_id must not be empty.').isLength({ min: 1 }).trim(),
    body('contract_id', 'book_id must not be empty.').isLength({ min: 1 }).trim(),
    body('tx_addr', 'tx_addr must not be empty.').isLength({ min: 1 }).trim(),
    body('block_number', 'block_number must not be empty.').isLength({ min: 1 }).trim(),

    // Sanitize fields.
    sanitizeBody('*').escape(),
    // Process request after validation and sanitization.
    (req, res, next) => {

        // Extract the validation errors from a request.
        const errors = validationResult(req);
        if (!errors.isEmpty()) {
            // There are errors. Render form again with sanitized values/error messages.
            res.status(400).send({ errors: errors.array() });
            return;
        }

        // Create a Book object with escaped/trimmed data
        var book_fields =
            {
                _id: req.body.book_id, // This is required, or a new ID will be assigned!
                status: 'on_loan'
            };

        // Create a contract object with escaped/trimmed data
        var contract_fields = {
            $push: {
                blk_data: {
                    tx_addr: req.body.tx_addr,
                    block_number: req.body.block_number
                }
            }
        };

        async.parallel({
            //call the function get book model
            book: function(callback) {
                Book.findByIdAndUpdate(req.body.book_id, book_fields, {}).exec(callback);
            },
            contract: function(callback) {
                Contract.findByIdAndUpdate(req.body.contract_id, contract_fields, {}).exec(callback);
            },
        }, function(error, results) {
            if (error) {
                res.status(400).send({ errors: errors.array() });
                return;
            }

            if ((results.book.isNew) || (results.contract.isNew)) {
                res.status(400).send({ errors: errors.array() });
                return;
            }

            var resObj = {
                "res": results.contract.url
            };
            res.status(200).send(JSON.stringify(resObj));
        });
    },
];
GoodApple
sumber