Множество функций в функции restify для клиента Flexiblesearch

Я создаю REST API с использованием узла и обновляю эти сообщения с помощью базы данных asticsearch. Теперь, когда я удаляю объект, я хочу, чтобы это выполняло каскадное удаление некоторых других объектов. Я знаю, что на самом деле это не то, для чего нужно использовать эластичный поиск, но терпите меня.

Итак, вот мой код:

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);
        }

Из моего кода я не получу никакого ответа.

1 ответ

Решение

Вы должны изменить свой код следующим образом (см. Изменения, обозначенные как -> налево):

    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 вместо библиотеки (см. пример использования 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. Эта функция позволяет вам сделать все вышеизложенное в одном запросе.

Если вы все еще используете ES 1.x, удаление по запросу все еще является частью ядра, и вы можете просто вызвать deleteByQuery функция клиента Javascript.

Если вы используете ES 2.x, удаление по запросу теперь является плагином, поэтому вам нужно установить его, а затем также потребовать библиотеку расширений 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();
        }
    });
}
Другие вопросы по тегам