restify函数中的多个函数到elasticsearch客户端
Multiple functions in restify function to elasticsearch client
我正在使用 node 构建 REST API 并重新验证它与 elasticsearch 数据库的通信。现在,当我删除一个对象时,我希望它对其他一些对象执行一种级联删除。我知道这不是使用 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);
}
在我的代码中,我不会得到任何响应。
您需要像这样更改您的代码(请参阅左侧 ->
表示的更改):
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);
我现在正在解释每个更改:
- 如果不这样做,
return
将发送错误,然后继续处理匹配
- (3/5) 由于
client.delete
是一个异步函数,需要在匿名函数中调用
- 如果出现错误,您需要调用
next(error)
而不是 res.send
- 此时您无法发送响应,因为您的 for 循环可能尚未终止。而不是 for 循环,你应该使用下面的优秀
async
library instead (see an example of using 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。该功能允许您在单个查询中完成上述所有操作。
如果你还在ES1.x,查询删除仍然是核心的一部分,你可以简单地调用Javascript客户端的deleteByQuery
function。
如果您使用的是 ES 2.x,按查询删除现在是一个插件,所以您需要 install it and then also require the 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();
}
});
}
我正在使用 node 构建 REST API 并重新验证它与 elasticsearch 数据库的通信。现在,当我删除一个对象时,我希望它对其他一些对象执行一种级联删除。我知道这不是使用 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);
}
在我的代码中,我不会得到任何响应。
您需要像这样更改您的代码(请参阅左侧 ->
表示的更改):
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);
我现在正在解释每个更改:
- 如果不这样做,
return
将发送错误,然后继续处理匹配 - (3/5) 由于
client.delete
是一个异步函数,需要在匿名函数中调用 - 如果出现错误,您需要调用
next(error)
而不是res.send
- 此时您无法发送响应,因为您的 for 循环可能尚未终止。而不是 for 循环,你应该使用下面的优秀
async
library instead (see an example of usingasynch.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。该功能允许您在单个查询中完成上述所有操作。
如果你还在ES1.x,查询删除仍然是核心的一部分,你可以简单地调用Javascript客户端的deleteByQuery
function。
如果您使用的是 ES 2.x,按查询删除现在是一个插件,所以您需要 install it and then also require the 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();
}
});
}