Come definire correttamente un oggetto nell'array nello schema Mongoose con l'indice geografico 2d


113

Al momento sto riscontrando problemi nella creazione di uno schema per il documento seguente. La risposta dal server restituisce sempre i valori del campo "trk" come [Object]. In qualche modo non ho idea di come dovrebbe funzionare, poiché ho provato almeno tutti gli approcci che avevano senso per me ;-)

Se questo aiuta, la mia versione di Mongoose è 3.6.20 e MongoDB 2.4.7 E prima che mi dimentichi, sarebbe bello impostarlo anche come Index (2d)

Dati originali:

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

Schema della mangusta:

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

La risposta dalla scheda Rete in Chrome è sempre simile a questa (è solo la parte trk che è sbagliata):

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

Ho già provato diverse definizioni dello schema per "trk":

  1. trk: Schema.Types.Mixed
  2. trk: [Schema.Types.Mixed]
  3. trk: [{type: [Number], index: "2d"}]

Spero che tu possa aiutarmi ;-)

Risposte:


219

Puoi dichiarare trk nei seguenti modi: - o

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

o

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

Nel secondo caso durante l'inserimento crea l'oggetto e spingilo nell'array come

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

oppure puoi impostare l'Array of object da

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

qualche idea su come denominare i campi html in tal caso, ad esempio nel caso in cui abbiamo bisogno di memorizzare un array di oggetti javascript nel database? Ad esempio, denominare i campi come trk.late trk.lngin html non funzionerà.
Raeesaa

3
trk: {type: Array, "default": []} funziona meglio per me! È semplice ed elegante!
Spiralmoon

1
@DpGeek se si dichiara un array in quel formato non è possibile aggiornare direttamente il campo dell'array. Per aggiornare direttamente l'array ho usato {lat: String, lng: String} subschema. Se non vuoi quella struttura allora trk: {type: Array, "default": []} sarà il migliore altrimenti devi dichiarare il sottoschema.
Kundu

l'impostazione predefinita senza virgolette ha funzionato per metrk : { type : Array , default : ['item1', 'item2'] }
Shardul

1
funzionerebbe ancora se i campi "lat" e "lng" fossero definiti come numero anziché come stringa?
jimijazz

63

Ho avuto un problema simile con la mangusta:

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

In effetti, stavo usando "tipo" come nome di proprietà nel mio schema:

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

Per evitare questo comportamento, devi modificare il parametro in:

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

4
diavolo sì, non ci ho nemmeno pensato. Questo ha risolto il mio problema proprio prima che stavo per iniziare a sbattere cose sulla mia scrivania ahah grazie di nuovo. D'ora in poi eviterò semplicemente di "digitare" nei miei schemi di mangusta.
blackops

Puoi fare un esempio del json che stavi cercando di inserire?
owensmartin

1
oppure potresti passare l'opzione typeKey al tuo generatore di schemi per sovrascrivere la dichiarazione del tipo
jimijazz

2

Grazie per le risposte.

Ho provato il primo approccio, ma non è cambiato nulla. Quindi, ho provato a registrare i risultati. Ho appena approfondito livello per livello, fino a quando sono finalmente arrivato al punto in cui i dati venivano visualizzati.

Dopo un po 'ho trovato il problema: quando stavo inviando la risposta, la stavo convertendo in una stringa tramite .toString().

L'ho risolto e ora funziona perfettamente. Ci scusiamo per il falso allarme.


1

Il problema che devo risolvere è memorizzare i contratti contenenti pochi campi (indirizzo, libro, num_of_days, mutuatario_addr, blk_data), blk_data è un elenco di transazioni (numero di blocco e indirizzo di transazione). Questa domanda e risposta mi hanno aiutato. Vorrei condividere il mio codice come di seguito. Spero che questo ti aiuti.

  1. Definizione dello schema. Vedi 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. Crea un record per la raccolta in MongoDB. Vedi 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. Aggiorna un record. Vedi 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));
        });
    },
];
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.