【问题标题】:Multiple functions in restify function to elasticsearch client向elasticsearch客户端恢复功能中的多个功能
【发布时间】:2018-11-02 18:28:44
【问题描述】:

我正在使用节点构建一个 REST API,并重新确定与弹性搜索数据库的通信。现在,当我删除一个对象时,我希望它对其他一些对象执行一种级联删除。我知道这不是使用 elasticsearch 的真正目的,但请耐心等待。

这是我的代码:

function deleteHostname(req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    var endpoints = [];

    client.search({
        index: 'test',
        type: 'something',
        body: {
            from: 0, size: 100,
            query: {
                match: {
                    hostname: 'www.test.com'
                }
            }
        }
    }).then(function (error, resp) {
        if(error) {
            res.send(error);
        }

        endpoints = resp.hits.hits;

        for (index = 0, len = endpoints.length; index < len; ++index) {
            client.delete({
                index: 'test',
                type: 'something',
                id: endpoints[index]._id
            }, function (error, response) {
                if(error) {
                    res.send(error);
                }
            });
        }

        res.send(endpoints);
        return next();
    });
}

所以基本上我只想搜索主机名为 www.test.com 的任何对象(我只是硬编码来测试它)。然后我想删除我找到的所有对象。它遵循错误路径并发送给我:

{  
   "took":1,
   "timed_out":false,
   "_shards":{  
      "total":5,
      "successful":5,
      "failed":0
   },
   "hits":{  
      "total":1,
      "max_score":2.098612,
      "hits":[  
         {  
            "_index":"test",
            "_type":"something",
            "_id":"123456",
            "_score":2.098612,
            "_source":{  
               "duration":107182,
               "date":"2016-05-04 00:54:43",
               "isExceptional":true,
               "hostname":"www.test.com",
               "eta":613,
               "hasWarnings":false,
               "grade":"A+",
               "ipAddress":"ipip",
               "progress":100,
               "delegation":2,
               "statusMessage":"Ready"
            }
         }
      ]
   }
}

所以在我看来这看起来不像一个错误?那么为什么我把它作为一个错误返回呢?如果我删除:

        if(error) {
            res.send(error);
        }

从我的代码中,我不会得到任何响应。

【问题讨论】:

    标签: rest elasticsearch restify elasticsearch-api


    【解决方案1】:

    您需要像这样更改您的代码(请参阅左侧-&gt; 表示的更改):

        if(error) {
    1->     return res.send(error);
        }
    
        endpoints = resp.hits.hits;
    
        for (index = 0, len = endpoints.length; index < len; ++index) {
    2->     (function(id){
                client.delete({
                    index: 'test',
                    type: 'something',
    3->             id: id
                }, function (error, response) {
                    if(error) {
    4->                 next(error);
                    }
                });
    5->     })(endpoints[index._id]);
        }
    
    6-> //res.send(endpoints);
    

    我现在解释每个变化:

    1. 如果您不return,您将发送错误,然后您将继续处理匹配项
    2. (3/5) 由于client.delete是异步函数,需要在匿名函数中调用
    3. 如果出现错误,您需要致电next(error) 而不是res.send
    4. 此时您无法发送响应,因为您的 for 循环可能尚未终止。您应该使用出色的 async 库而不是 for 循环(请参阅下面的使用 asynch.each 的示例)

    异步示例:

        var async = require('async');
        ...
    
        if(error) {
            return res.send(error);
        }
    
        endpoints = resp.hits.hits;
    
        async.each(endpoints, 
            function(endpoint, callback) {
                client.delete({
                   index: 'test',
                   type: 'something',
                   id: endpoint._id
                }, callback);
            }, 
            // this is called when all deletes are done
            function(err){
                if (err) {
                    next(err);
                } else {
                    res.send(endpoints);
                    next();
                }
            }
        );
    

    另一种实现您想要的解决方案是使用delete by query plugin。该功能允许您在单个查询中完成上述所有操作。

    如果你还在使用 ES 1.x,delete-by-query 仍然是核心的一部分,你可以简单地调用 Javascript 客户端的deleteByQuery function

    如果你在 ES 2.x 上,delete-by-query 现在是一个插件,所以你需要 install it 然后还需要 deleteByQuery Javascript 客户端扩展库

    function deleteHostname(req, res, next) {
        res.setHeader('Access-Control-Allow-Origin', '*');
    
        client.deleteByQuery({
            index: 'test',
            type: 'something',
            body: {
               query: {
                   match: { hostname: 'www.test.com' }
               }
            }
        }, function (error, response) {
            if (error) {
                next(error);
            } else {
                res.send(endpoints);
                next();
            }
        });
    }
    

    【讨论】:

    • 好的,所以我不得不再改变一件事,由于某种原因,它总是给我一个错误,而实际上它是响应,所以我将 .then(function (error, resp) { 更改为 .then (function(resp) { 只是给我响应,现在它可以工作了!
    • 哦,是的,好点,我错过了,then 回调没有任何错误参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-08
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-10
    相关资源
    最近更新 更多