日期:2014-05-16  浏览次数:20613 次

mongodb学习中的困惑,希望能得到大家的帮助。
各位好,我目前遇到个问题,困扰了好久,希望大家能够给个指点。我们项目之前用的mysql,但考虑以后的数据量的发展趋势,考虑用mongodb,但就目前测试的情况而言,处理速度不是很理想,但我又担心是因为我自己测试有误,所以想听听各位的意见,谢谢。

mysql中有三个表:item(id,name)、theme(id,word)、itemtheme(itemid,themeid,word,type,weight);

其中item 和theme是多对多的关系,所以抽出关系表itemtheme用于存放关联关系。

现在的业务逻辑是 做这样的一个操作   需要根据若干个theme.word查出 具有这些 word的item,并按照这若干个word的weight之和倒序排列,取出前200个itemid,举例说:

itemtheme中有


itemid themeid word type weight
101 11 china 1 100
101 12 gps 2 200
101 13 iphone 3 300
102 12 gps 1 100
102 13 iphone 2 200




根据上图的模拟数据,我的应用需要做这样的事情:找出 有china 和gps这两个word的itemid,然后对 china和gps这两个word的weight相加,然后按照这个和倒序排列,所以这个实例中得出的结果是 101 300.   sql语句 就是

select t1.itemid, (t1.weight + t2.weight) as sumWeight
from itemtheme t1
inner join itemtheme t2 on t1.itemid = t2.itemid
where t1.word= china and t2.word = gps
order by sumWeight desc;


现在我们向移植到mongodb上来,有一个集合叫做item 结构为:

{
        "_id" : ObjectId("4faae54a1ba46159a6ca4bfd"),
        "itemid" : 101,
        "name" : "iphone4s",
        "theme" : [
                {
                        "word" : "gps",
                        "weight" : 200,
                        "type" : 2
                },
                {
                        "word" : "china",
                        "weight" : 100,
                        "type" : 1
                }
        ]
}
所以为了完成上面的应用,我就用了mapreduce:

var mr = db.runCommand(
{
mapreduce:"item",
map:function(){
  varid = this.itemid;
  this.theme.forEach(function(t){
  if((t.word =="gps")||(t.word =="china")){
     emit(id,{weight:t.weight,word:t.word});
   }
  });
},
reduce:function(key,values){
  sumWeight = 0;
   for(var i=0;i<values.length;i++){
     var w = values[i].word;
     sumWeight += values[i].weight;
    }
   return{"weight":sumWeight};
},
query:{
   "theme.word":
       {
           $all:
              [
                "gps",
                "china"