猫鼬场比赛填充

时间:2013-12-19 21:05:29

标签: node.js mongodb mongoose

我在如何最好地在mongoose中实现此连接/查询时遇到了一些麻烦。

var mongoose = require('mongoose');
var addressSchema = new mongoose.Schema{
                    rank: Number, 
                    address: String,
                    tag_name: String,
                    tag_url: String};

var tagSchema = new mongoose.Schema{
                    address: String, 
                    name: String,
                    url: String};

我保存了一堆地址并保存了一堆标签。有些地址有标签,大部分都没有。我经常单独更新地址和标签。我想要做的是查询一些特定的地址并将它们作为一个数组返回,并填入标记字段(地址标记字段在数据库中为空)。

因此,例如,我想在不为每个地址进行db查询的情况下执行此操作(示例中为101 db查询)。我不确定$ match或$ in或populate是否是我正在寻找的。以下代码未经测试,可能无效,但它应该让您了解我正在尝试做什么。

var db = require('../config/dbschema');

// find an array of addresses
db.addressModel.find({ rank: { $lte: 100 } }, function(err, addresses) {
  // now fill in the tag fields and print
  addTagField(0, addresses);
});

// recursive function to fill in tag fields
// address tag name and tag url fields are blank in the database
function addTagField(n, addresses) {
  if(n < addresses.length) {
    db.tagModel.find( { address: addresses[n].address }, function(err, tag) {
      // if find a tag with this address, fill in the fields
      // otherwise leave blank and check next address in array
      if(tag) {
        addresses[n].tag_name = tag.name;
        addresses[n].tag_url = tag.url;
      }
      addTagField(n+1, addresses);
    });
  } else {
    console.log(addresses);
  }
}

http://mongoosejs.com/docs/api.html#aggregate_Aggregate-match http://mongoosejs.com/docs/api.html#query_Query-in http://mongoosejs.com/docs/api.html#document_Document-populate

我想用更少的数据库查询来完成上述操作。

2 个答案:

答案 0 :(得分:1)

你的主要问题是你没有利用Mongoose的关系映射。稍微改变您的模式,您的问题将很容易解决。你可以这样做:

var tagSchema = new Schema({
    name: String,
    url: String,
})

var addressSchema = new Schema ({
    rank: Number, 
    address: String,
    tags: [tagSchema],
})

addressModel.find({rank: {$lte: 100}}, function(err, addresses) {
    ...
})

或者这个:

var tagSchema = new Schema({
    name: String,
    url: String,
})

var addressSchema = new Schema ({
    rank: Number, 
    address: String,
    tags: [{type: ObjectId, ref: 'Tag'}],
})

addressModel
    .find({rank: {$lte: 100}})
    .populate('tags', 'name url')
    .exec(function(err, addresses) {
        ...
    })

答案 1 :(得分:0)

我不想嵌入文档。这就是我想出来的。

db.addressModel.find({ rank: { $lte: 100 } }, function(err, addresses) {
  if(err) return res.send(400);
  if(!addresses) return res.send(404);
  var addrOnlyAry = addresses.map(function(val, idx) { return val.address; });
  db.tagModel.find( { address: { $in: addrOnlyAry } }, {}, function(err, tags) {
    if(err) return res.send(400);
    if(tags.length > 0) addresses = setTagFields(addresses, tags);
    return res.json(addresses);
  }
}

function setTagFields(addresses, tags) {
  for(var i=0; i < tags.length; i++) {
    for(var j=0; j < addresses.length; j++) {
      if(addresses[j].address === tags[i].address) {
        addresses[j].tag_name = tags[i].tag;
        addresses[j].tag_url = tags[i].url;
        break;
      }
    }
  }
  return addresses;
}