如何动态更新文档的字段?

时间:2017-03-28 03:07:35

标签: node.js elasticsearch

我正在构建一个用于存储电影/电视节目的基本crud应用程序。我正在使用elasticsearch的2.4.4版,因为我的项目经理选择了这个版本。我正在使用express框架和本地elasticsearch nodejs驱动程序。

目前这就是我的映射对于"标题" "标题的索引"类型。

client.indices.create({
      index: "titles",
      body: {
        "mappings": {
          "title": {
            "properties": {
              "seriesName":           { "type": "string", "index": "not_analyzed" },
              "seriesEpisodeNumber":  { "type": "long", "index": "not_analyzed" },
              "seriesEpisodeTitle":   { "type": "string", "index": "not_analyzed" },
              "isDeleted":            { "type": "boolean", "index": "not_analyzed" }
            }
          }
        }
      }
    }).

我想在我的服务器上有一个端点,用于通过id更新文档。这就是我到目前为止这个终点所用的#34; POST / api / titles /:titleID / updateTitleByID"

titlesController.updateTitleByID = function(req,res){
  const titleID = req.params.titleID;
  es.updateByQuery({
    index: "titles",
    type: "title",
    body: {
      query: {
        bool: {
          must: [{
            term: {
              _id: titleID
            }},{
              term: {
                isDeleted: false 
              }}]
        }
      },
      script: {
        inline: "ctx._source.seriesName = seriesName;ctx._source.seriesEpisodeNumber = seriesEpisodeNumber; ctx._source.seriesEpisodeTitle = seriesEpisodeTitle;",
        params: { ...req.body }
      }
    }}).then(results => {
      logger.info(results);
      res.status(200).json({
        message: "OK"
      });
    }).catch(err => {
      logger.error(err);
      res.status(500).json({
        error: "Internal server error"
      });
    });
};

我想要实现的是使用我从req.body获得的内容来更新文档。例如,如果我从请求正文中获得了一个seriesName I.这只是我想要更新的内容,其余部分保持不变。我如何实现这一目标?

编辑:这是完整的堆栈跟踪

Error: [remote_transport_exception] [Agon][127.0.0.1:9300][indices:data/write/update[s]]
    at respond (/home/natealcedo/Projects/digitalfolks.hooq/node_modules/elasticsearch/src/lib/transport.js:289:15)
    at checkRespForFailure (/home/natealcedo/Projects/digitalfolks.hooq/node_modules/elasticsearch/src/lib/transport.js:248:7)
    at HttpConnector.<anonymous> (/home/natealcedo/Projects/digitalfolks.hooq/node_modules/elasticsearch/src/lib/connectors/http.js:164:7)
    at IncomingMessage.wrapper (/home/natealcedo/Projects/digitalfolks.hooq/node_modules/lodash/lodash.js:4968:19)
    at emitNone (events.js:91:20)
    at IncomingMessage.emit (events.js:186:7)
    at endReadableNT (_stream_readable.js:974:12)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickDomainCallback (internal/process/next_tick.js:122:9)

1 个答案:

答案 0 :(得分:1)

如果您想要更新单个文档,则不需要使用逐个查询的端点,Update API绰绰有余,因为它支持partial updates,这正是你追求的是什么。您需要使用update call代替:

titlesController.updateDocByID = function(req,res){
  const titleID = req.params.titleID;
  const partialFields = req.body;
  // TODO do some validations on the received fields
  es.update({
    index: "titles",
    type: "title",
    id: titleID,
    body: {
      doc: partialFields
    }}).then(results => {
      logger.info(results);
      res.status(200).json({
        message: "OK"
      });
    }).catch(err => {
      logger.error(err);
      res.status(500).json({
        error: "Internal server error"
      });
    });
};

如果您只需要在isDeleted标志为false时更新文档,那么您可以使用相同的API调用但使用脚本,如下所示:

titlesController.updateDocByID = function(req,res){
  const titleID = req.params.titleID;
  const partialFields = req.body;
  // TODO do some validations on the received fields
  es.update({
    index: "titles",
    type: "title",
    id: titleID,
    body: {
      script: "if (!ctx._source.isDeleted) { ctx._source.putAll(params.partialFields) }",
      params: {partialFields: partialFields}
    }}).then(results => {
      logger.info(results);
      res.status(200).json({
        message: "OK"
      });
    }).catch(err => {
      logger.error(err);
      res.status(500).json({
        error: "Internal server error"
      });
    });
};

如果您使用第二种方法,则需要在elasticsearch.yml配置文件中enable dynamic scripting