So definieren Sie ein Objekt im Array im Mongoose-Schema korrekt mit dem 2d-Geoindex

112

Ich habe derzeit Probleme beim Erstellen eines Schemas für das folgende Dokument. Die Antwort vom Server gibt immer die Feldwerte "trk" als [Objekt] zurück. Irgendwie habe ich keine Ahnung, wie das funktionieren soll, da ich zumindest alle Ansätze ausprobiert habe, die für mich Sinn machten ;-)

Wenn dies hilft, ist meine Mongoose-Version 3.6.20 und MongoDB 2.4.7. Und bevor ich es vergesse, wäre es schön, sie auch als Index (2d) festzulegen.

Originale Daten:

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

Mungo-Schema:

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

Die Antwort auf der Registerkarte "Netzwerk" in Chrome sieht immer so aus (das ist nur der falsche trk-Teil):

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

Ich habe bereits verschiedene Schemadefinitionen für "trk" ausprobiert:

  1. trk: Schema.Types.Mixed
  2. trk: [Schema.Types.Mixed]
  3. trk: [{Typ: [Nummer], Index: "2d"}]

Hoffe du kannst mir helfen ;-)

niels_h
quelle

Antworten:

218

Sie können trk folgendermaßen deklarieren: - entweder

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

oder

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

Im zweiten Fall beim Einfügen machen Sie das Objekt und schieben Sie es wie in das Array

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

oder Sie können das Array des Objekts durch festlegen

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
quelle
Gibt es eine Idee, wie man HTML-Felder in einem solchen Fall benennt, dh für den Fall, dass wir ein Array von Javascript-Objekten in einer Datenbank speichern müssen? Zum Beispiel funktioniert das Benennen von Feldern als trk.latund trk.lngin HTML nicht.
Raeesaa
3
trk: {type: Array, "default": []} funktioniert am besten für mich! Es ist einfach und elegant!
Spiralmond
1
@DpGeek Wenn Sie ein Array in diesem Format deklarieren, können Sie das Array-Feld nicht direkt aktualisieren. Um das Array direkt zu aktualisieren, habe ich das Teilschema {lat: String, lng: String} verwendet. Wenn Sie diese Funktion nicht möchten, ist trk: {type: Array, "default": []} die beste, sonst müssen Sie das Teilschema deklarieren.
Kundu
Standard ohne Anführungszeichen funktionierte für michtrk : { type : Array , default : ['item1', 'item2'] }
Shardul
1
würde es immer noch funktionieren, wenn die Felder 'lat' und 'lng' als Zahl anstelle von Zeichenfolge definiert würden?
Jimijazz
63

Ich hatte ein ähnliches Problem mit Mungo:

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

Tatsächlich habe ich "Typ" als Eigenschaftsnamen in meinem Schema verwendet:

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

Um dieses Verhalten zu vermeiden, müssen Sie den Parameter ändern in:

fields: [
    {
      name: String,
      type: {
        type: { type: String }
      },
      registrationEnabled: Boolean,
      checkinEnabled: Boolean
    }
  ]
Pierre Maoui
quelle
4
verdammt ja, habe nicht mal darüber nachgedacht. Das hat mein Problem gelöst, kurz bevor ich anfangen wollte, Sachen auf meinen Schreibtisch zu knallen, haha, nochmals vielen Dank. Ich werde von nun an vermeiden, meine Mungo-Schemata einzugeben.
Blackops
Können Sie ein Beispiel für den JSON geben, den Sie einfügen wollten?
Owensmartin
1
oder Sie können die typeKey-Option an Ihren Schema-Builder übergeben, um die Typdeklaration zu überschreiben
jimijazz
2

Danke für die Antworten.

Ich habe den ersten Ansatz versucht, aber nichts hat sich geändert. Dann habe ich versucht, die Ergebnisse zu protokollieren. Ich habe nur Level für Level einen Drilldown durchgeführt, bis ich endlich dort ankam, wo die Daten angezeigt wurden.

Nach einer Weile fand ich das Problem: Als ich die Antwort sendete, konvertierte ich sie über in einen String .toString().

Ich habe das behoben und jetzt funktioniert es hervorragend. Entschuldigung für den Fehlalarm.

niels_h
quelle
1

Das Problem, das ich lösen muss, besteht darin, Verträge zu speichern, die einige Felder enthalten (Adresse, Buch, Anzahl der Tage, Kreditnehmeradresse, blk_data). Blk_data ist eine Transaktionsliste (Blocknummer und Transaktionsadresse). Diese Frage und Antwort hat mir geholfen. Ich möchte meinen Code wie folgt teilen. Hoffe das hilft.

  1. Schemadefinition. Siehe 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. Erstellen Sie einen Datensatz für die Sammlung in der MongoDB. Siehe 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. Aktualisieren Sie einen Datensatz. Siehe 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
quelle