Re-index logstash-* trong ElasticElastic để search special characters
Elasticsearch
5
TIL
499
White

Cùi Bắp viết ngày 20/12/2017

Tiêu đề #TIL ko chuẩn lắm cơ mà thôi :joy:

Sự nghiệp đi code thuê đôi khi gặp phải những yêu cầu quái gở :trollface:. Mình đã từng search kí tự đặc biệt (Ví dụ: * / ~ & # . !) trong MySQL, thực sự ko có gì khó khăn với câu lệnh LIKE, nhưng sang tới Elasticsearch thì không được mỳ ăn liền cho lắm. :poop:

Hiện tại bên mình đang đi làm lại cái bánh xe :satisfied: Khách hàng ko thích xài kibana nữa, muốn làm lại 1 cái tương tự thế :disappointed_relieved: việc dev gặp khá nhiều vấn đề và đây là 1 trong số những yêu cầu quái dị !

Các câu lệnh trong bài viết các bạn có thể chạy trong [Dev Tools] của Kibana cho tiện.

1. Đầu tiên hãy xem thông tin về index của logstash

Console: GET /logstash-2017.12.19

Refers: https://www.elastic.co/guide/en/elasticsearch/reference/current/indices.html

{
  "logstash-2017.12.19": {
    "aliases": {},
    "mappings": {
      "_default_": {
        ...
      },
      "doc": {
        "dynamic_templates": [
          {
            "message_field": {
              "path_match": "message",
              "match_mapping_type": "string",
              "mapping": {
                "norms": false,
                "type": "text"
              }
            }
          },
          {
            "string_fields": {
              "match": "*",
              "match_mapping_type": "string",
              "mapping": {
                "fields": {
                  "keyword": {
                    "ignore_above": 256,
                    "type": "keyword"
                  }
                },
                "norms": false,
                "type": "text"
              }
            }
          }
        ],
        "properties": {
          "@timestamp": {
            "type": "date"
          },
          "@version": {
            "type": "keyword"
          },
          "geoip": {
            "dynamic": "true",
            "properties": {
              "ip": {
                "type": "ip"
              },
              "latitude": {
                "type": "half_float"
              },
              "location": {
                "type": "geo_point"
              },
              "longitude": {
                "type": "half_float"
              }
            }
          },
          "host": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "message": {
            "type": "text",
            "norms": false
          }
        }
      }
    },
    "settings": {
      "index": {
        "refresh_interval": "5s",
        "number_of_shards": "5",
        "provided_name": "logstash-2017.12.19",
        "creation_date": "1513649744840",
        "number_of_replicas": "1",
        "uuid": "EivjOTEfQOKRQsFJqUvi2g",
        "version": {
          "created": "6000199"
        }
      }
    }
  }
}

Dĩ nhiên nếu bạn gặp lỗi index_not_found_exception thì cũng ko sao cả, vì trên máy bạn ko có index này :relieved: . Để tạo ra nó hãy dùng logstash nhé. Nếu ngại thì có thể xem môi trường build sẵn tại đây :expressionless:

2. Nghĩ về Analysis và Analyzers

At index time, if no analyzer has been specified, it looks for an analyzer in the index settings called default. Failing that, it defaults to using the standard analyzer.

Okay, index trên ko chỉ định Analyzer ! Đến đây hãy nghĩ tới yêu cầu mà KH cho bạn, chúng ta cần phải xem với index này thì việc phân tách từ sẽ ra sao ?

Refers: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis.html

Console:

GET /logstash-2017.12.19/_analyze
{
  "analyzer": "standard",
  "text": "We are looking for .NET, C++ and C# developers !"
}

Kết quả là:

{
  "tokens": [
    {
      "token": "we",
      "start_offset": 0,
      "end_offset": 2,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "are",
      "start_offset": 3,
      "end_offset": 6,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "looking",
      "start_offset": 7,
      "end_offset": 14,
      "type": "<ALPHANUM>",
      "position": 2
    },
    {
      "token": "for",
      "start_offset": 15,
      "end_offset": 18,
      "type": "<ALPHANUM>",
      "position": 3
    },
    {
      "token": "net",
      "start_offset": 20,
      "end_offset": 23,
      "type": "<ALPHANUM>",
      "position": 4
    },
    {
      "token": "c",
      "start_offset": 25,
      "end_offset": 26,
      "type": "<ALPHANUM>",
      "position": 5
    },
    {
      "token": "and",
      "start_offset": 29,
      "end_offset": 32,
      "type": "<ALPHANUM>",
      "position": 6
    },
    {
      "token": "c",
      "start_offset": 33,
      "end_offset": 34,
      "type": "<ALPHANUM>",
      "position": 7
    },
    {
      "token": "developers",
      "start_offset": 36,
      "end_offset": 46,
      "type": "<ALPHANUM>",
      "position": 8
    }
  ]
}

(orz) trong các token (term) ko hề có sự xuất hiện của kí tự đặc biệt như #, +, !, . Thế này thì search kiểu mẹ gì :joy:

Như vậy trong trường hợp này ta nên sử dụng tokenizerwhitespace thay vì dùng punctuation, digit, lowercase :confused:

"analysis" : {
  "analyzer":{
    "custom_analyzer":{
       "type": "custom",
       "filter": [
          "lowercase"
       ],
       "tokenizer": "whitespace"
    }
  }
}

2. Áp dụng dynamic template cho logstash

Đến đây lại gặp vấn đề làm thế nào để thay đổi được cấu hình index, mỗi khi logstash tạo ra 1 index mới . :tired_face:
Để ý 1 chút, index nào cũng theo pattern: logstash-YYYY.MM.DD. Ngồi ngâm tài liệu tiếp thì bắt gặp câu sau:

One of the most important features of Elasticsearch is that it tries to get out of your way and let you start exploring your data as quickly as possible. To index a document, you don’t have to first create an index, define a mapping type, and define your fields — you can just index a document and the index, type, and fields will spring to life automatically.

Kéo kéo xuống chút, và chúng ta có gì, từ khoá mới: Dynamic templates (Tất nhiên là chỉ mới với mình :ok_hand:). Dynamic template giúp bạn có thể khai báo custom mappings được áp dụng một cách hoàn toàn tự động vào các indices được chỉ định trong template đó !


Try hard ...


Tiến hành tạo template cho các indices được tạo ra bởi logstash, trong này ta đã âm thầm thiết lập analyzer cho field message

Console:

PUT _template/template_logstash
{
    "index_patterns" : "logstash-*",
    "version": 1,
    "settings" : {
        "analysis" : {
          "analyzer":{
            "custom_analyzer":{
               "type": "custom",
               "filter": [
                  "lowercase"
               ],
               "tokenizer": "whitespace"
            }
          }
        }
    },
    "mappings": {
      "doc": {
        "properties": {
          "message": {
            "type": "text",
            "analyzer": "custom_analyzer"
          }
        }
      }
    }
}

Ok, và template đã được tạo, test kiểu gì đây, chẳng nhẽ phải đợi tới ngày hôm sau để kiểm chứng những gì ta đang làm là đúng đắn :question: Ko sao, tôi xoá mịe nó index của ngày hôm nay đi =))

Lưu ý: Trên Production thì đừng có nghịch dại nhé, tìm hiểu thêm https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html để có thể create lại index với dữ liệu cũ vì bản thân elasticsearch ko cho thay đổi cấu hình mapping của index đã tạo trước đó.

In general, the mapping for existing fields cannot be updated. 
There are some exceptions to this rule. For instance:
- new properties can be added to Object datatype fields.
- new multi-fields can be added to existing fields.
- the ignore_above parameter can be updated.

Console: DELETE logstash-2017.12.19

kết quả là:

{
  "acknowledged": true
}

:clap: Đợi tí, logstash nó lại thêm 1 index là logstash-2017.12.19
Nào bây giờ cùng xem thử ra sao:

Console: GET logstash-2017.12.19

Đã thấy:

{
  "logstash-2017.12.19": {
    "aliases": {},
    "mappings": {
      "_default_": {
        ...
      },
      "doc": {
        ...
        "properties": {
          "@timestamp": {
            "type": "date"
          },
          ...
          "message": {
            "type": "text",
            "analyzer": "custom_analyzer"
          }
        }
      }
    },
    "settings": {
      "index": {
        ...
        "analysis": {
          "analyzer": {
            "custom_analyzer": {
              "filter": [
                "lowercase"
              ],
              "type": "custom",
              "tokenizer": "whitespace"
            }
          }
        },
         ...
      }
    }
  }
}

Túc tiệp thử tách từ phát:

Console:

GET /logstash-2017.12.19/_analyze
{
  "analyzer": "standard",
  "text": "We are looking for .NET, C++ and C# developers !"
}

Kết quả là:

{
  "tokens": [
    {
      "token": "we",
      "start_offset": 0,
      "end_offset": 2,
      "type": "word",
      "position": 0
    },
    {
      "token": "are",
      "start_offset": 3,
      "end_offset": 6,
      "type": "word",
      "position": 1
    },
    {
      "token": "looking",
      "start_offset": 7,
      "end_offset": 14,
      "type": "word",
      "position": 2
    },
    {
      "token": "for",
      "start_offset": 15,
      "end_offset": 18,
      "type": "word",
      "position": 3
    },
    {
      "token": ".net,",
      "start_offset": 19,
      "end_offset": 24,
      "type": "word",
      "position": 4
    },
    {
      "token": "c++",
      "start_offset": 25,
      "end_offset": 28,
      "type": "word",
      "position": 5
    },
    {
      "token": "and",
      "start_offset": 29,
      "end_offset": 32,
      "type": "word",
      "position": 6
    },
    {
      "token": "c#",
      "start_offset": 33,
      "end_offset": 35,
      "type": "word",
      "position": 7
    },
    {
      "token": "developers",
      "start_offset": 36,
      "end_offset": 46,
      "type": "word",
      "position": 8
    },
    {
      "token": "!",
      "start_offset": 47,
      "end_offset": 48,
      "type": "word",
      "position": 9
    }
  ]
}

Thấy gì chưa, các kí tự ., !, +, # xuất hiện trong term rồi nhé :blue_heart:

3. Insert dữ liệu và test lại

Ta thử thêm vào 2 bản ghi sau bằng các lệnh bên dưới.

Console:

PUT /logstash-2017.12.19/doc/1
{
  "message": "We are looking for .NET, C++ and C# developers !"
}
PUT /logstash-2017.12.19/doc/2
{
  "message": "Full Stack: Agile Web Developer (React/Angular, JavaScript, C#, MVC/Razor)"
}

Full text queries

:point_right: Tìm thử 1 từ nào

Console:

POST /logstash-2017.12.19/_search
{
  "query": { 
    "match_phrase": {
      "message": "C#"
    }
  },
  "size": 10
}

Kết quả

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1.162498,
    "hits": [
      {
        "_index": "logstash-2017.12.19",
        "_type": "doc",
        "_id": "1",
        "_score": 1.162498,
        "_source": {
          "message": "We are looking for .NET, C++ and C# developers !"
        }
      }
    ]
  }
}

Tìm với Multi Match Query

Console:

POST /logstash-2017.12.19/_search
{
  "query": {
    "bool": {
      "should": [
        { 
          "match": {"message": "# developer"}
        },
        {
          "match_phrase_prefix": {"message": "# developer"}
        },
        {
          "wildcard": {"message": "*# developer*"}
        }
      ]
    }
  },
  "size": 10
}

Term level queries

:point_right: Tìm thử 1 kí tự xem sao =))

Console:

GET /logstash-2017.12.19/_search
{
  "query": { 
    "wildcard": {
      "message": "*(*"
    }
  },
  "size": 10
}

Kết quả

{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "logstash-2017.12.19",
        "_type": "doc",
        "_id": "2",
        "_score": 1,
        "_source": {
          "message": "Full Stack: Agile Web Developer (React/Angular, JavaScript, C#, MVC/Razor)"
        }
      }
    ]
  }
}

:point_right: Thử thêm phát nữa

Console:

GET /logstash-2017.12.19/_search
{
  "query": { 
    "wildcard": {
      "message": "*\\#*"
    }
  },
  "size": 10
}

Kết quả

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 1,
    "hits": [
      {
        "_index": "logstash-2017.12.19",
        "_type": "doc",
        "_id": "2",
        "_score": 1,
        "_source": {
          "message": "Full Stack: Agile Web Developer (React/Angular, JavaScript, C#, MVC/Razor)"
        }
      },
      {
        "_index": "logstash-2017.12.19",
        "_type": "doc",
        "_id": "1",
        "_score": 1,
        "_source": {
          "message": "We are looking for .NET, C++ and C# developers !"
        }
      }
    ]
  }
}

Okay, mọi thứ đều all, pass qua test case của Khách hàng, nhưng chắc chắn đây không phải là 1 hướng đi tốt :trollface:

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Cùi Bắp

16 bài viết.
78 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
66 3
Bài viết này được dịch từ (Link) https://code.facebook.com/ mà theo mình khá hữu ích đối với web developer. Trong hai năm qua, Facebook đã làm việ...
Cùi Bắp viết 1 năm trước
66 3
White
44 9
Bài viết này xin đề cập tới Nginx Load balancing 1. Thế nào Load Balancing Load Balancing hay còn gọi là Cân bằng tải ?? một kỹ thuật thường đượ...
Cùi Bắp viết hơn 1 năm trước
44 9
White
18 0
Nhân tiện vừa đọc bài viết liên quan tới OpenCV trên Kipalog, nên em xin giới thiệu về giải thuật sinh ảnh mosaic từ một ảnh gốc. Không hiểu sinh ả...
Cùi Bắp viết gần 2 năm trước
18 0
Bài viết liên quan
White
5 0
About elasticsearch memory control Elasticsearch rất dễ bị die bởi OOM(OutOfMemory) bởi memory trên ES được dùng intensive trong rất nhiều logic k...
huydx viết 1 năm trước
5 0
White
51 9
Elasticsearch là gì (Ảnh) Elasticsearch chắc hẳn là nhiều người đã biết, nhưng để bài viết trơn tru, cứ phải có cái introduction cho nó dài. Elas...
huydx viết 7 tháng trước
51 9
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
16 bài viết.
78 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!