2016-05-03 9 views
0

Ich baue eine REST-API mit Knoten und restified diese Kommunikation mit einer ElasticSearch-Datenbank. Wenn ich jetzt ein Objekt lösche, möchte ich eine Art kaskadierendes Löschen für einige andere Objekte durchführen. Ich weiß, das ist nicht wirklich, was Elasticsearch zu verwenden, aber mit mir bare.Mehrere Funktionen in Restify-Funktion zu elasticsearch Client

So, hier ist mein Code:

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

Also im Grunde nur suchen, möchte ich für alle Objekte mit dem Hostnamen www.test.com (ich nur schwer diese codiert, es zu testen). Dann möchte ich alle gefundenen Objekte löschen. Es folgt der Fehlerpfad und schickt mir folgendes:

{ 
    "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" 
      } 
     } 
     ] 
    } 
} 

Also meiner Meinung nach sieht das nicht wie ein Fehler aus? Warum bekomme ich es als Fehler zurück? Wenn ich entferne:

Von meinem Code werde ich keine Antwort erhalten.

Vielen Dank im Voraus für jede Hilfe oder Anregungen.

Antwort

1

Sie benötigen Code wie folgt (siehe die Änderungen von -> nach links bezeichnet) zu ändern:

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

Ich erkläre jetzt jede Änderung:

  1. Wenn Sie nicht tun return senden Sie den Fehler und dann werden Sie mit der Verarbeitung der Treffer
  2. (3/5) fortfahren Da client.delete eine asynchrone Funktion ist, müssen Sie es in einer anonymen Funktion
  3. aufrufen
  4. Im Fehlerfall müssen Sie next(error) anrufen, nicht res.send
  5. Sie können die Antwort zu diesem Zeitpunkt nicht senden, da Ihre for-Schleife möglicherweise noch nicht beendet ist. Statt einer for-Schleife, sollten Sie die ausgezeichnete async Bibliothek verwenden statt (siehe ein Beispiel asynch.each unter Verwendung)

Async Beispiel:

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

Eine andere Lösung für Sie genau das erreichen, was Sie wollen, ist um die zu verwenden. Mit dieser Funktion können Sie alle oben genannten Aufgaben in einer einzigen Abfrage ausführen.

Wenn Sie noch auf ES 1.x sind, ist delete-by-query immer noch Teil des Kerns und Sie können einfach die deleteByQuery function des Javascript-Clients aufrufen.

Wenn Sie auf ES 2.x sind, löschen-by-Abfrage ist nun ein Plugin, so yo Notwendigkeit install it und dann erfordern auch die deleteByQuery Erweiterungsbibliothek für die Javascript-Client

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(); 
     } 
    }); 
} 
+0

Ok, so hatte ich um noch eine Sache zu ändern, aus irgendeinem Grund gab es mir immer einen Fehler, während es tatsächlich die Antwort war, also änderte ich dann (Funktion (Fehler, resp)) zu. Dann (Funktion (resp)), um mir nur die Antwort zu geben und jetzt funktioniert es! – Matthias

+0

Oh ja, guter Punkt, das habe ich verpasst, der dann Callback hat kein Fehlerargument. – Val