使用Mongoose

时间:2015-06-11 08:29:50

标签: node.js mongodb mongoose

首先,让我首先提供我的MongoDB架构。

showTitle: String,
seasons: [{
  seasonNumber: String,
  episodes: [{
      episodeNumber: String,
      episodeTitle: String,
      episodeSynopsis: String
            }]  
         }]

此系列的基本理念是存储电视节目详情。电视节目可以包含多个季节,每个季节包含多个剧集。

我允许用户在客户端添加额外的季节(只有seasonNumber)。这会将值传递给服务器端。这部分工作得很好,因为我可以在我的服务器端console.log查看值,一个字符串。

在这里,我的API调用了这个特定的函数。

function saveReport(err, res, count, seasonId, seasonDetails)
{
  if(count == 0) //if 0 means not exist, so can add into DB
  {
    Show.update({_id: seasonId},{$push: {seasons:{seasonNumber: [seasonDetails]}}}, {upsert:true}, function(err, result)
    {
      console.log(result);
      res.json(result);
    });
  }
  else
  {
    res.json("TV Season already exists in MongoDB");
  }
}

module.exports.seasonsCreate = function(req, res)
{
  console.log("Calling the seasonsCreate function");
  var seasonId = req.params.id;
  var seasonDetails = req.body.season; //season number as a string(intended)

 //finding a specific showing using the id passed as parameter
 //$elemMatch is used to check if season number exists
 //using count to determine
  Show.findOne({_id: req.params.id, seasons: {$elemMatch: {seasonNumber: req.body.season}}}).count(function(err, count)
  {
    saveReport(err, res, count, seasonId, seasonDetails);
  });
}

我手动(使用MongoDB命令)在MongoDB中添加了两个季节。第1季和第2季各有2集。但是,当我尝试通过客户端添加第3集时,没有任何反应。返回的确切结果是:

  

对象{ok:0,n:0,nModified:0}

我在使用类似方法之前已完成更新。但是,我有点被抛弃,因为这次我有嵌套数组而不仅仅是对象。我也尝试了几种组合:

  • 有/无推送
  • 有/无设置
  • 有/无upsert

我很确定问题是我更新数据库的方式。希望有人能在这里说清楚。谢谢!!

p / s:我使用的是Mongoose的最新版本。

1 个答案:

答案 0 :(得分:4)

由于我感觉到人们告诉您.find()数据然后.save()发出危险的错误建议,我会解释"展平&#34的基本情况;数据以避免嵌套数组问题。

嵌套数组遇到的问题是,您需要使用positional $ operator来匹配要更新的所需数组元素的索引,只能引用"外部"数组元素。虽然这可能很好地识别该元素和"推"对于该元素的内部数组,如果您想更新该内部元素,则无法获取内部元素的位置。

所以这里的想法是“不是嵌套数组"”和结构,这样你就可以在可用的约束内实际有效地更新。

更好的结构是:

showTitle: String,
episodes: [{
  seasonNumber: String,
  episodeNumber: String,
  episodeTitle: String,
  episodeSynopsis: String
}]

现在你不会在这里放松任何东西,它只是一点额外的重复数据,但成本很低。

要添加到数组:

Show.update({ "_id": showId },{ "$push": { "episodes": episodeData } },callback)

更新元素:

Show.update(
    { 
       "_id": showId,
       "episodes": { 
           "$elemMatch": {
               "seasonNumber": season,
               "episodeNumber": episode
           }
       }
    },
    { "$set": { "episodes.$": episodeData } },
    callback
)

甚至:

Show.update(
    { 
       "_id": showId,
       "episodes": { 
           "$elemMatch": {
               "seasonNumber": season,
               "episodeNumber": episode
           }
       }
    },
    { "$set": { "episodes.$.episodeSynopsis": synopis } },
    callback
)

如果你只想要一季的所有剧集:

Show.aggregate(
    [
        { "$match": { "_id": showId, "epsisodes.seasonNumber": seasonNumber } },
        { "$redact": {
            "if": { 
                "$eq": [
                    { "$IfNull": [ "$seasonNumber", seasonNumber ] } },
                    seasonNumber
                ]
            },
            "then": "$DESCEND",
            "else": "$PRUNE"
        }}
    ],
    callback
)

在查询中返回时,会从数组中剔除任何不匹配的条目。

因此,您可以在更改数据存储时轻松完成所需的一切,并使用原子更新,这些更新不会遇到其他操作的问题,从而将数据转换为意外状态,因为您可以从其中冒险。