我正在尝试让ElasticSearch使用v1.4x中的Completion Suggesters为我的自动完成服务索引内容。我正在关注ElasticSearch - You Complete Me的建议并使用Go Client olivere/elastic。
我的索引方法看起来有点像这样:
func IndexVehicle(client *elastic.Client, vehicle Vehicle) (bool, error) {
// See if it exists already
fetch, err := client.Get().
Index(vehicleIndex).
Type("vehicle").
Id(vehicle.Id).
Do()
if err != nil || fetch.Found {
return false, err
}
vehicleName := fmt.Sprintf("%s %s (%s) %s", vehicle.Make, vehicle.Model, vehicle.Model_year, vehicle.Primary_fuel)
suggest := elastic.NewSuggestField()
suggest.Input(vehicle.Make, vehicle.Model, vehicle.Primary_fuel, vehicle.Model_year).
Output(vehicleName).
Payload(vehicle)
// Go forth and save
put, err := client.Index().
Index(vehicleIndex).
Type("vehicle").
Id(vehicle.Id).
Debug(true).Pretty(true).
BodyJson(indexBody{Name: vehicleName, Suggest: suggest}).
Do()
if err != nil {
return false, err
}
return put.Created, nil
}
现在奇怪的是,在我的一些测试中,这种方法工作正常,项目将被编入索引。在擦除和重建索引之后的其他测试中,测试将失败:
早期的测试在调试中看起来像这样:
2014/12/15 14:11:37 PUT /vehicle/vehicle/369f96459b340507c4688740da3bfe1a?pretty=true HTTP/1.1
Host: localhost:9200
User-Agent: elastic/1.3.1 (darwin-amd64)
Transfer-Encoding: chunked
Accept: application/json
Content-Type: application/json
Accept-Encoding: gzip
{"name":"American Motors Corporation Eagle 4WD (1986) regular","suggest":{"input":["American Motors Corporation","Eagle 4WD","regular","1986"],"output":"American Motors Corporation Eagle 4WD (1986) regular","payload":{"make":"American Motors Corporation","model_year":"1986","model":"Eagle 4WD","primary_fuel":"regular","vehicle_class":"Special Purpose Vehicle 4WD","transmission":"Automatic 3-spd","displacement":"4.2","drive":"4-Wheel or All-Wheel Drive","city_mpg":"15.0","highway_mpg":"19.0","comb_mpg":"17.0"}}}
2014/12/15 14:11:37 HTTP/1.1 201 Created
Content-Length: 134
Content-Type: application/json; charset=UTF-8
{
"_index" : "vehicle",
"_type" : "vehicle",
"_id" : "369f96459b340507c4688740da3bfe1a",
"_version" : 1,
"created" : true
}
但是在以后的测试中,做同样的事情会导致错误。在以后的测试中从err
返回的IndexVehicle()
是:
E
Errors:
* /Users/phil/go/src/github.com/ride/autocomplete/vehicle_test.go
Line 79: - elastic: Error 400: ElasticsearchIllegalArgumentException[No feature for name [vehicle]]
goroutine 245 [running]:
github.com/ride/autocomplete.func·033()
/Users/phil/go/src/github.com/ride/autocomplete/vehicle_test.go:79 +0x249
github.com/ride/autocomplete.useIndex(0x499e98)
/Users/phil/go/src/github.com/ride/autocomplete/test_helper.go:18 +0x55
github.com/ride/autocomplete.func·034()
/Users/phil/go/src/github.com/ride/autocomplete/vehicle_test.go:96 +0x2a
github.com/jtolds/gls._m(0x0, 0xc2080ae9e0)
/Users/phil/go/src/github.com/jtolds/gls/stack_tags.go:70 +0x32
github.com/jtolds/gls.markS(0x0, 0xc2080ae9e0)
/Users/phil/go/src/github.com/jtolds/gls/stack_tags.go:21 +0x32
github.com/jtolds/gls.addStackTag(0x0, 0xc2080ae9e0)
/Users/phil/go/src/github.com/jtolds/gls/stack_tags.go:18 +0x3e
github.com/jtolds/gls.(*ContextManager).SetValues(0xc20801e080, 0xc2080b31d0, 0xc2080ae9e0)
/Users/phil/go/src/github.com/jtolds/gls/context.go:98 +0x503
github.com/ride/autocomplete.TestSearchForVehicles(0xc20806a480)
/Users/phil/go/src/github.com/ride/autocomplete/vehicle_test.go:97 +0x243
testing.tRunner(0xc20806a480, 0x5be890)
/opt/boxen/homebrew/Cellar/go/1.4/libexec/src/testing/testing.go:447 +0xbf
created by testing.RunTests
/opt/boxen/homebrew/Cellar/go/1.4/libexec/src/testing/testing.go:555 +0xa8b
goroutine 1 [chan receive]:
testing.RunTests(0x49a078, 0x5be800, 0x7, 0x7, 0x67c001)
/opt/boxen/homebrew/Cellar/go/1.4/libexec/src/testing/testing.go:556 +0xad6
testing.(*M).Run(0xc2080463c0, 0x5c9b20)
/opt/boxen/homebrew/Cellar/go/1.4/libexec/src/testing/testing.go:485 +0x6c
main.main()
github.com/ride/autocomplete/_test/_testmain.go:64 +0x1d5
goroutine 208 [chan receive]:
github.com/olivere/elastic.(*Client).pinger(0xc208106d40)
/Users/phil/go/src/github.com/olivere/elastic/client.go:79 +0x6b
created by github.com/olivere/elastic.NewClient
/Users/phil/go/src/github.com/olivere/elastic/client.go:60 +0x26e
goroutine 248 [runnable]:
net/http.(*persistConn).readLoop(0xc20802e4d0)
/opt/boxen/homebrew/Cellar/go/1.4/libexec/src/net/http/transport.go:928 +0x9ce
created by net/http.(*Transport).dialConn
/opt/boxen/homebrew/Cellar/go/1.4/libexec/src/net/http/transport.go:660 +0xc9f
goroutine 98 [chan receive]:
github.com/olivere/elastic.(*Client).pinger(0xc208033e00)
/Users/phil/go/src/github.com/olivere/elastic/client.go:79 +0x6b
created by github.com/olivere/elastic.NewClient
/Users/phil/go/src/github.com/olivere/elastic/client.go:60 +0x26e
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/opt/boxen/homebrew/Cellar/go/1.4/libexec/src/runtime/asm_amd64.s:2232 +0x1
goroutine 44 [chan receive]:
github.com/olivere/elastic.(*Client).pinger(0xc2080332c0)
/Users/phil/go/src/github.com/olivere/elastic/client.go:79 +0x6b
created by github.com/olivere/elastic.NewClient
/Users/phil/go/src/github.com/olivere/elastic/client.go:60 +0x26e
goroutine 249 [select]:
net/http.(*persistConn).writeLoop(0xc20802e4d0)
/opt/boxen/homebrew/Cellar/go/1.4/libexec/src/net/http/transport.go:945 +0x41d
created by net/http.(*Transport).dialConn
/opt/boxen/homebrew/Cellar/go/1.4/libexec/src/net/http/transport.go:661 +0xcbc
goroutine 54 [chan receive]:
github.com/olivere/elastic.(*Client).pinger(0xc208032f80)
/Users/phil/go/src/github.com/olivere/elastic/client.go:79 +0x6b
created by github.com/olivere/elastic.NewClient
/Users/phil/go/src/github.com/olivere/elastic/client.go:60 +0x26e
goroutine 76 [chan receive]:
github.com/olivere/elastic.(*Client).pinger(0xc208032e00)
/Users/phil/go/src/github.com/olivere/elastic/client.go:79 +0x6b
created by github.com/olivere/elastic.NewClient
/Users/phil/go/src/github.com/olivere/elastic/client.go:60 +0x26e
goroutine 250 [chan receive]:
github.com/olivere/elastic.(*Client).pinger(0xc208106c40)
/Users/phil/go/src/github.com/olivere/elastic/client.go:79 +0x6b
created by github.com/olivere/elastic.NewClient
/Users/phil/go/src/github.com/olivere/elastic/client.go:60 +0x26e
goroutine 120 [chan receive]:
github.com/olivere/elastic.(*Client).pinger(0xc208106b00)
/Users/phil/go/src/github.com/olivere/elastic/client.go:79 +0x6b
created by github.com/olivere/elastic.NewClient
/Users/phil/go/src/github.com/olivere/elastic/client.go:60 +0x26e
goroutine 142 [chan receive]:
github.com/olivere/elastic.(*Client).pinger(0xc208106e00)
/Users/phil/go/src/github.com/olivere/elastic/client.go:79 +0x6b
created by github.com/olivere/elastic.NewClient
/Users/phil/go/src/github.com/olivere/elastic/client.go:60 +0x26e
goroutine 164 [chan receive]:
github.com/olivere/elastic.(*Client).pinger(0xc208106b80)
/Users/phil/go/src/github.com/olivere/elastic/client.go:79 +0x6b
created by github.com/olivere/elastic.NewClient
/Users/phil/go/src/github.com/olivere/elastic/client.go:60 +0x26e
goroutine 186 [chan receive]:
github.com/olivere/elastic.(*Client).pinger(0xc208106d00)
/Users/phil/go/src/github.com/olivere/elastic/client.go:79 +0x6b
created by github.com/olivere/elastic.NewClient
/Users/phil/go/src/github.com/olivere/elastic/client.go:60 +0x26e
goroutine 230 [chan receive]:
github.com/olivere/elastic.(*Client).pinger(0xc208106dc0)
/Users/phil/go/src/github.com/olivere/elastic/client.go:79 +0x6b
created by github.com/olivere/elastic.NewClient
/Users/phil/go/src/github.com/olivere/elastic/client.go:60 +0x26e
可能这个回溯中更重要的部分是:
错误400:ElasticsearchIllegalArgumentException [没有名称[vehicle]的功能]
所以,不知道这里到底出了什么问题。我在索引上有1秒的超时,因为这个客户端不支持“等待绿色”逻辑[还]。
func ResetVehicleIndex(client *elastic.Client) (err error) {
if _, err = client.DeleteIndex(vehicleIndex).Do(); err != nil {
return
}
if _, err = EnsureVehicleIndex(client); err != nil {
return
}
// TODO: This is awful. Switch to "wait for green" when elastic client supports it
time.Sleep(time.Second * 1)
return nil
}
这适用于大多数其他测试,因为elasticsearch似乎在一秒左右就准备好了,但是无论代码中的等待时间如何,这些测试都会一直出错。
有什么想法吗?我可能需要编辑问题以添加更多代码或更好的解释,但我会快速回答任何问题,特别是如果你在Twitter @philsturgeon上ping我。我真的很困惑。
答案 0 :(得分:10)
该异常是only triggered in one place,这是在Get Index API调用期间。这意味着您的车辆ID必须为空:
fetch, err := client.Get().
Index(vehicleIndex).
Type("vehicle").
Id(vehicle.Id). //<-- this
Do()
您正在尝试使用格式为GET /{index}/{type}/{id}
的Get Document API。但是,您的客户并没有区分Get Document和Get Index API调用......并且它不会验证您的参数是否为空。
因此,如果将null vehicle.Id
传递给Get方法,那么您的最终网址实际上将为GET /{index}/{type}/
从Elasticsearch的角度来看,这不再是Get Document API调用......它实际上是一个Get Index调用,它具有以下格式:GET /{index}/{feature}
。功能可以是以下之一:_settings
,_mappings
,_aliases
或_warmers
。
由于vehicle
不是这些功能之一,因此ES会抛出异常并喷出。您可以从控制台验证这一点:
curl -XGET localhost:9200/my_index/vehicle/
答案 1 :(得分:0)
为了完整性:当我用“post”而不是“POST”初始化我的请求方法时,我遇到了同样的错误
像这样:req, _ := http.NewRequest("post", url, query)
// returns: Error 400: ElasticsearchIllegalArgumentException[No feature for name [_bulk]]
req, _ := http.NewRequest("POST", url, query)
// works just fine