Skip to main content

严格模式还是无模式?

Quickwit 让您能够选择您的模式有多严格。换句话说,您可以以非常严格的映射方式运行 Quickwit,也可以完全无模式的方式运行,或者介于两者之间的任何程度。让我们来看看具体如何操作!

note

要执行本指南中的 CLI 命令,请安装 Quickwit 并在终端中使用以下命令启动服务器:

./quickwit run

严格的映射

这是最直接的方法。 作为用户,您需要精确定义 Quickwit 要索引的字段列表。

例如,一个合理的应用日志映射可能是:

version: 0.7

index_id: my_strict_index

doc_mapping:
mode: strict # <--- The mode attribute
field_mappings:
- name: timestamp
type: datetime
input_formats:
- unix_timestamp
output_format: unix_timestamp_secs
fast_precision: seconds
fast: true
- name: server
type: text
tokenizer: raw
- name: message
type: text
record: position
- name: severity
tokenizer: raw
timestamp_field: timestamp

search_settings:
default_search_fields: [severity, message]

indexing_settings:
commit_timeout_secs: 30

mode 属性控制着如果摄入的文档包含未在文档映射中定义的字段时应采取的操作。默认情况下,您的索引处于 dynamic 模式。在 dynamic 模式下,未出现在文档映射中的字段将以无模式的方式进行索引。 详情请参见 动态模式部分

如果将 mode 设置为 strict,包含未定义字段的文档将被完全丢弃。

最后,mode 的另一个可能值是 lenient。在 lenient 模式下,未出现在字段映射中的字段将被简单忽略。

动态模式:部分模式下的无模式

mode 可以取值:dynamic。 当设置为 dynamic 时,所有额外的字段实际上将使用一个通配配置进行映射。

默认情况下,这个通配配置会索引并存储所有这些字段,但这可以通过设置 dynamic_mapping 属性 进行配置。 一个极简但完全有效且有用的索引配置如下:

version: 0.7
index_id: my_dynamic_index
doc_mapping:
mode: dynamic

这种配置使得可以摄入任何 JSON 对象并搜索它们。

然而,动态模式也可以与字段映射结合使用。 这种组合特别适用于无法映射到单一模式的事件日志。

例如,考虑以下用户事件日志:

{
"timestamp": 1653021741,
"user_id": "8705a7fak",
"event_type": "login",
"ab_groups": ["phoenix-red-ux"]
}
{
"timestamp": 1653021746,
"user_id": "7618fe06",
"event_type": "order",
"ab_groups": ["phoenix-red-ux", "new-ranker"],
"cart": [
{
"product_id": 120391,
"product_description": "Cherry Pi: A single-board computer that is compatible..."
}
]
}
{
"timestamp": 1653021748,
"user_id": "8705a7fak",
"event_type": "login",
"ab_groups": ["phoenix-red-ux"]
}

每种事件类型都有其自身的属性集。将我们的映射声明为所有这些特定事件映射的并集将是一项繁琐的工作。

相反,我们可以挑选所有日志中通用的字段,并依赖动态模式处理其余部分。

version: 0.7
index_id: my_dynamic_index
doc_mapping:
mode: dynamic
field_mappings:
- name: timestamp
type: datetime
input_formats:
- unix_timestamp
output_format: unix_timestamp_secs
fast_precision: seconds
fast: true
- name: user_id
type: text
tokenizer: raw
- name: event_type
type: text
tokenizer: raw
timestamp_field: timestamp

indexing_settings:
commit_timeout_secs: 30 # <--- Your document will be searchable ~30 seconds after you ingest them.

我们的索引现在已准备好处理类似的查询:

event_type:order AND cart.product_id:120391

执行以下命令以创建索引、导入几个文档并进行搜索:

cat << EOF > my_dynamic_index.yaml
version: 0.7
index_id: my_dynamic_index
doc_mapping:
mode: dynamic
field_mappings:
- name: timestamp
type: datetime
input_formats:
- unix_timestamp
output_format: unix_timestamp_secs
fast_precision: seconds
fast: true
- name: user_id
type: text
tokenizer: raw
- name: event_type
type: text
tokenizer: raw
timestamp_field: timestamp

indexing_settings:
commit_timeout_secs: 30
EOF

# Create index.
./quickwit index create --index-config ./my_dynamic_index.yaml --overwrite --yes

cat << EOF > my_logs.json
{"timestamp":1653021741,"user_id":"8705a7fak","event_type":"login","ab_groups":["phoenix-red-ux"]}
{"timestamp":1653021746,"user_id":"7618fe06","event_type":"order","ab_groups":["phoenix-red-ux","new-ranker"],"cart":[{"product_id":120391,"product_description":"Cherry Pi: A single-board computer that is compatible..."}]}
{"timestamp":1653021748,"user_id":"8705a7fak","event_type":"login","ab_groups":["phoenix-red-ux"]}
EOF

# Ingest documents.
./quickwit index ingest --index my_dynamic_index --input-path my_logs.json --force

# Execute search query.
./quickwit index search --index my_dynamic_index --query "event_type:order AND cart.product_id:120391

带有无模式字段的模式

一些日志将这些特定于事件的属性隔离在一个子字段中。例如,让我们看一下 OpenTelemetry JSON 日志。

{
"Timestamp": 1653028151,
"Attributes": {
"split_id": "28f897f2-0419-4d88-8abc-ada72b4b5256"
},
"Resource": {
"service": "donut_shop",
"k8s_pod_uid": "27413708-876b-4652-8ca4-50e8b4a5caa2"
},
"TraceId": "f4dbb3edd765f620",
"SpanId": "43222c2d51a7abe3",
"SeverityText": "INFO",
"SeverityNumber": 9,
"Body": "merge ended"
}

在这个日志中,AttributesResource 字段包含任意的键值对。

Quickwit 0.3 引入了一种 JSON 字段类型来处理这种情况。一个好的索引配置可以是:

version: 0.7
index_id: otel_logs
doc_mapping:
mode: dynamic
field_mappings:
- name: Timestamp
type: datetime
fast: true
input_formats:
- unix_timestamp
output_format: unix_timestamp_secs
fast_precision: seconds
fast: true
- name: Attributes
type: json
tokenizer: raw
- name: Resource
type: json
tokenizer: raw
- name: TraceId
type: text
tokenizer: raw
- name: SpanId
type: text
tokenizer: raw
- name: SeverityText
type: text
tokenizer: raw
fast: true
- name: Body
type: text
timestamp_field: Timestamp

search_settings:
default_search_fields: [SeverityText, Body, Attributes, Resource]

indexing_settings:
commit_timeout_secs: 10

我们现在可以使用以下查询自然地搜索我们的日志:

merge AND service:donuts_shop

让我们执行以下命令以创建索引、导入一个文档并执行搜索查询:

# Create index.
./quickwit index create --index-config ./otel_logs.yaml --overwrite --yes

cat << EOF > otel_logs.json
{"Timestamp":1653028151,"Attributes":{"split_id":"28f897f2-0419-4d88-8abc-ada72b4b5256"},"Resource":{"service":"donut_shop","k8s_pod_uid":"27413708-876b-4652-8ca4-50e8b4a5caa2"},"TraceId":"f4dbb3edd765f620","SpanId":"43222c2d51a7abe3","SeverityText":"INFO","SeverityNumber":9,"Body":"merge ended"}
EOF

# Ingest documents.
./quickwit index ingest --index otel_logs --input-path otel_logs.json --force

# Execute search query.
./quickwit index search --index otel_logs --query "merge AND service:donut_shop"