【问题标题】:How to define object in array in Mongoose schema correctly with 2d geo index如何使用 2d 地理索引在 Mongoose 模式中正确定义数组中的对象
【发布时间】:2013-11-10 18:46:44
【问题描述】:

我目前在为以下文档创建架构时遇到问题。来自服务器的响应总是将“trk”字段值返回为 [Object]。不知何故,我不知道这应该如何工作,因为我至少尝试了所有对我有意义的方法;-)

如果这有帮助,我的 Mongoose 版本是 3.6.20 和 MongoDB 2.4.7 在我忘记之前,最好也将其设置为 Index (2d)

原始数据:

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

Mongoose 架构:

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

Chrome 中“网络”选项卡的响应总是如下所示(这只是 trk 部分错误):

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

我已经为“trk”尝试了不同的架构定义:

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

希望你能帮助我;-)

【问题讨论】:

    标签: node.js mongodb mongoose schema geo


    【解决方案1】:

    您可以通过以下方式声明 trk :- 要么

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

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

    在插入过程中的第二种情况下,制作对象并将其推送到数组中,如

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

    或者你可以设置对象数组

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

    【讨论】:

    • 知道如何在这种情况下命名 html 字段,即如果我们需要在数据库中存储一个 javascript 对象数组?例如,在 html 中将字段命名为 trk.lattrk.lng 将不起作用。
    • trk : { type : Array , "default" : [] } 最适合我!简洁优雅!
    • @DpGeek 如果您以该格式声明数组,则无法直接更新数组字段。为了直接更新数组,我使用了 {lat : String,lng : String} 子模式。如果您不想要该设施,那么 trk : { type : Array , "default" : [] } 将是最好的,否则您必须声明子模式。
    • 默认不带引号对我有用trk : { type : Array , default : ['item1', 'item2'] }
    • 如果 'lat' 和 'lng' 字段定义为数字而不是字符串,它是否仍然有效?
    【解决方案2】:

    感谢您的回复。

    我尝试了第一种方法,但没有任何改变。然后,我尝试记录结果。我只是逐层钻取,直到我最终到达显示数据的位置。

    过了一会儿,我发现了问题:当我发送响应时,我通过.toString()将其转换为字符串。

    我解决了这个问题,现在它运行良好。很抱歉误报。

    【讨论】:

      【解决方案3】:

      我对猫鼬有类似的问题:

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

      事实上,我在架构中使用“类型”作为属性名称:

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

      为避免这种行为,您必须将参数更改为:

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

      【讨论】:

      • 见鬼,根本没想到。这解决了我的问题,就在我开始在我的桌子上砸东西之前哈哈再次感谢。从现在开始,我将避免在我的猫鼬模式中使用“类型”。
      • 你能举一个你试图插入的json的例子吗?
      • 或者您可以将 typeKey 选项传递给您的架构构建器以覆盖类型声明
      【解决方案4】:

      我需要解决的问题是存储包含几个字段(地址、账簿、num_of_days、borrower_addr、blk_data)的合约,blk_data 是一个交易列表(区块号和交易地址)。 这个问题和答案帮助了我。我想分享我的代码如下。希望这会有所帮助。

      1. 架构定义。请参阅 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. 为 MongoDB 中的集合创建记录。请参阅 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. 更新记录。请参阅 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));
              });
          },
      ];
      

      【讨论】:

        【解决方案5】:

        为了在模式中创建一个数组,我们必须再创建一个模式为monetizationSchema,它用于一次存储一个数据,另一个作为blogSchema 我们有monetization 字段包含monetizationSchema,方括号为一个数组。

        Schema 一次存储一个数据。

        const monetizationSchema = new Schema({
              amazonUrl: {
                type: String,
                required: true,
              } 
            });
        

        monetization 为数组的架构。

        const blogSchema = {
          monetization: [
           monetizationSchema
          ],
          image: {
           type: String,
           required: true
          },
          // ... etc
        });
        

        【讨论】:

          【解决方案6】:

          你可以像下面这样声明一个数组

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

          但它会将 [] (空数组)设置为默认值,如果您不希望此默认值覆盖此默认值,则需要将默认值设置为未定义为下面

          trk: {
              type: [{
                  lat : String,
                  lng : String
              }],
              default: undefined
          }
          

          【讨论】:

            猜你喜欢
            • 2020-06-24
            • 2017-02-10
            • 1970-01-01
            • 2021-11-27
            • 2023-04-10
            • 2012-09-17
            • 2017-10-15
            • 2020-12-04
            • 2018-04-15
            相关资源
            最近更新 更多