
作为 Elasticsearch 用户,我们从许多不同的位置收集数据。 我们使用 Logstash、Beats 和其他工具来抓取数据并将它们发送到 Elasticsearch。 有时,我们无法控制数据本身,我们需要管理数据的结构,甚至需要在摄取数据时处理字段名称。
Elasticsearch 有一些保留的字段名称,你不能在文档中使用这些名称。
如果文档具有这些字段之一,则无法为该文档编制索引。 但是,这并不意味着你不能在文档中的任何地方使用这些字段名称。 该限制仅对根节点(root node)有效。 因此,你无法索引以下文档:
PUT twitter/_doc/1
{
"_id": 1
}
你会得到如下错误:

但是你可以成功地写入如下的文档:
PUT twitter/_doc/1
{
"user": {
"_id": 1,
"name": "liuxg"
}
}
究其原因,在上面的 _id 它不是在 root node 下的字段。
因此,正如你在上面看到的 _id 字段,你不能在文档中使用以下字段名称作为 root 字段名称:
_id
_field_names
_index
_seq_no
_nested_path
_ignored
_routing
_data_stream_timestamp
_tier
_version
_feature
_source
_primary_term *
_type *
注意:上面用 * 标注的字段对于老版本的 elasticsearch 这个字段也是保留关键字
这意味着如果你有将这些字段名称作为根字段的文档。 你会得到一个错误。 例如,你想使用 Logstash 移动该数据。 你有一个包含如下内容的文件:
{
"ImdbId": "tt0030629",
"_id": "tt0030629",
"name": "Prison Without Bars",
"year": "1938",
"certificate": "Approved",
"runtime": "72 min",
"genre": ["Crime", " Drama", " Romance"],
"ratingValue": "6.2",
"summary_text": "Suzanne, Renee, Nina and Marta all hate being in prison, being slapped and treated badly, and so all the girls are trying to escape. Madame Appel just causes chaos all the time, with her ... See full summary\u00a0\u00bb",
"ratingCount": "66"
}
{
"ImdbId": "tt0030528",
"_id": "tt0030528",
"name": "Orage",
"year": "1938",
"certificate": "",
"runtime": "98 min",
"genre": ["Drama"],
"ratingValue": "5.7",
"summary_text": "Orage is a 1938 French drama film directed by Marc All\u00e9gret. The screenplay was written by Marcel Achard and H.G. Lustig, based on play \"Le venin\" by Henri Bernstein. The films stars ... See full summary\u00a0\u00bb",
"ratingCount": "66"
}
因此,当你尝试使用 Logstash 摄取它时,你将收到以下错误。 即使你在单独索引这些文档时也会遇到上述错误。比如我们使用如下的一个例子:
sample.log
{"_id":1,"timestamp":"2019-09-12T13:43:42Z","paymentType":"Amex","name":"Merrill Duffield","gender":"Female","ip_address":"132.150.218.21","purpose":"Toys","country":"United Arab Emirates","age":33}
{"_id":2,"timestamp":"2019-08-11T17:55:56Z","paymentType":"Visa","name":"Darby Dacks","gender":"Female","ip_address":"77.72.239.47","purpose":"Shoes","country":"Poland","age":55}
{"_id":3,"timestamp":"2019-07-14T04:48:25Z","paymentType":"Visa","name":"Harri Cayette","gender":"Female","ip_address":"227.6.210.146","purpose":"Sports","country":"Canada","age":27}
{"_id":4,"timestamp":"2020-02-29T12:41:59Z","paymentType":"Mastercard","name":"Regan Stockman","gender":"Male","ip_address":"139.224.15.154","purpose":"Home","country":"Indonesia","age":34}
{"_id":5,"timestamp":"2019-08-03T19:37:51Z","paymentType":"Mastercard","name":"Wilhelmina Polle","gender":"Female","ip_address":"252.254.68.68","purpose":"Health","country":"Ukraine","age":51}
logstash_input.conf
input {
file {
path => "//Users/liuxg/elastic/logstash-8.6.2/sample.log"
type => "applog"
codec => "json"
start_position => "beginning"
sincedb_path => "/dev/null"
}
}
output {
stdout {
codec => rubydebug
}
elasticsearch {
hosts => ["localhost:9200"]
index => "json-%{+YYYY.MM.dd}"
}
}
我们使用如下的命令来启动对数据的采集:
$ pwd
/Users/liuxg/elastic/logstash-8.6.2
$ ls sample.log logstash_input.conf
logstash_input.conf sample.log
./bin/logstash -f logstash_input.conf

如你所见,错误与我们上面得到的错误相同。 那么,我们需要做什么? 有一些解决方案可以处理这些类型的数据操作。 你可以在源上修复文档,也可以使用 mutate 过滤器在 Logstash 中管理它们:
logstash_input.conf
input {
file {
path => "//Users/liuxg/elastic/logstash-8.6.2/sample.log"
type => "applog"
codec => "json"
start_position => "beginning"
sincedb_path => "/dev/null"
}
}
filter {
mutate {
rename => {"_id" => "id"}
}
}
output {
stdout {
codec => rubydebug
}
elasticsearch {
hosts => ["localhost:9200"]
index => "json-%{+YYYY.MM.dd}"
}
}
我们再次运行 Logstash:
./bin/logstash -f logstash_input.conf

我们可以看到这次数据被成功地写入,并且我们可以在 Kibana 中进行查看:

当您重新运行 logstash 时,您将看到文档将被正确索引。 另一方面,我试图解决摄取管道的问题。 一开始我认为这对我来说可能是一个更好的解决方案。 但有趣的是,我对摄取管道尝试了很多不同的方法,但我找不到解决方案。 这是我尝试使用摄取管道的方法:
POST _ingest/pipeline/_simulate
{
"pipeline": {
"processors": [
{
"rename": {
"field": "_id",
"target_field": "id"
}
}
]
},
"docs": [
{
"_index": "myindex",
"_id": 1,
"_source": {
"_id": "2"
}
}
]
}
我收到以下错误:
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "unexpected metadata [_id:1] in source"
}
],
"type": "illegal_argument_exception",
"reason": "unexpected metadata [_id:1] in source"
},
"status": 400
} 我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr
如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只
当我创建一个Rails应用程序时,控制台:railsnewfoo我的代码可以使用字符串“foo”吗?puts"Yourapp'snameis"+app_name_bar 最佳答案 Rails.application.class将为您提供应用程序的全名(例如YourAppName::Application)。从那里您可以使用Rails.application.class.parent获取模块名称。 关于ruby-on-rails-应用程序的名称是否可以作为变量使用?,我们在StackOve
已经有一个问题回答了如何将“America/Los_Angeles”转换为“PacificTime(US&Canada)”。但是我想将“美国/太平洋”和其他过时的时区转换为RailsTimeZone。我无法在图书馆中找到任何可以帮助我完成此任务的东西。 最佳答案 来自RailsActiveSupport::TimeZonedocs:TheversionofTZInfobundledwithActiveSupportonlyincludesthedefinitionsnecessarytosupportthezonesdefinedb
我几天前在我的rubyonrails2.3.2上安装了Sphinx和Thinking-Sphinx,基本搜索效果很好。这意味着,没有任何条件。现在,我想用一些条件过滤搜索。我有公告模型,索引如下所示:define_indexdoindexestitle,:as=>:title,:sortable=>trueindexesdescription,:as=>:description,:sortable=>trueend也许我错了,但我注意到只有当我将:sortable=>true语法添加到这些属性时,我才能将它们用作搜索条件。否则它找不到任何东西。现在,我还在使用acts_as_tag
假设您编写了一个类Sup,我决定将其扩展为SubSup。我不仅需要了解你发布的接口(interface),还需要了解你的私有(private)字段。见证这次失败:classSupdefinitialize@privateField="fromsup"enddefgetXreturn@privateFieldendendclassSub问题是,解决这个问题的正确方法是什么?看起来子类应该能够使用它想要的任何字段而不会弄乱父类(superclass)。编辑:equivalentexampleinJava返回"fromSup",这也是它应该产生的答案。 最佳答案
我使用rails3.1+rspec和factorygirl。我对必填字段(validates_presence_of)的验证工作正常。我如何让测试将该事实用作“成功”而不是“失败”规范是:describe"Addanindustrywithnoname"docontext"Unabletocreatearecordwhenthenameisblank"dosubjectdoind=Factory.create(:industry_name_blank)endit{shouldbe_invalid}endend但是我失败了:Failures:1)Addanindustrywithnona
如thisquestion,当在其自己的赋值中使用未定义的局部变量时,它的计算结果为nil。x=x#=>nil但是当局部变量的名称与现有的方法名称冲突时,就比较棘手了。为什么下面的最后一个示例返回nil?{}.instance_eval{a=keys}#=>[]{}.instance_eval{keys=self.keys}#=>[]{}.instance_eval{keys=keys}#=>nil 最佳答案 在Ruby中,因为可以在没有显式接收器和括号的情况下调用方法,所以在局部变量引用和无接收器无参数方法调用之间存在语法歧义:f