如何利用2d 地理索引正确定义猫鼬模式中的数组对象?

我目前在为下面的文档创建模式时遇到了问题。来自服务器的响应总是将“ 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
}]
}
}

猫鼬图式:

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”的不同 Schema 定义:

  1. 模式。类型。混合
  2. Trk: [ Schema。类型。混合]
  3. Trk: [{ type: [ Number ] ,index: “2d”}]

希望你能帮助我; -)

365763 次浏览

可以通过以下方式声明 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
}
});

或者可以通过以下方法设置 Array of object

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

谢谢你的回复。

我尝试了第一种方法,但什么都没有改变。然后,我试着记录结果。我只是一层一层地往下钻,直到我最终找到显示数据的地方。

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

我把它修好了,现在它运行得很好,很抱歉给你带来了错误的警报。

我对猫鼬也有类似的问题:

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

事实上,我在模式中使用“ type”作为属性名:

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

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

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

我需要解决的问题是存储包含几个字段的契约(address、 book、 num _ of _ days、  借款人 _ 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 中为集合创建一条记录。
// 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));
});
},
];

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

Schema用于一次存储一个数据。

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

monetization为数组的模式。

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

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

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

但是它会将 [](空数组)设置为默认值。

如果您不想要这个默认值,然后覆盖这个默认值,您需要将默认值设置为 undefined,如下所示

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