python建立elasticsearch索引的探討

weixin_33890526發表於2018-11-12

以前用elasticsearch都是先create index,然後傳送資料進去。但是最近有個需求,要自動建立索引,所以就只能使用elasticsearch的template功能。

直接上程式碼:

from elasticsearch import Elasticsearch
es = Elasticsearch()

t1 = {
    u'aliases': {},
    u'mappings': {
        u'_default_': {
            u'_source': {
                u'enabled': False
            },
            u'properties': {
                "title": {
                    "type": "text",
                    "analyzer": "ik_max_word",
                    "search_analyzer": "ik_max_word",
                },
            }
        }
    },
    u'order': 0,
    u'settings': {u'index': {u'number_of_shards': u'1'}},
    u'template': u'te*'
}


es.indices.put_template(name='test', body=t1, create=True)

這個時候顯示:

{u'acknowledged': True}

就表示template建立成功了。以後只要是建立以te為開頭的index,都會自動套用上面的模板設定,比如:

body = {'title': u'我到河北省來'}
es.create(index='test_001', doc_type='doc', body=body, id=1)

顯示成功後我們再檢視test_001的mapping:

es.indices.get_mapping(index='test_001')

顯示:

{
    u'test_001': {
        u'mappings': {
            u'_default_': {
                u'_source': {
                    u'enabled': False
                },
                u'properties': {
                    u'title': {
                        u'analyzer': u'ik_max_word',
                        u'type': u'text'
                    }
                }
            },
            u'doc': {
                u'_source': {
                    u'enabled': False
                },
                u'properties': {
                    u'title': {
                        u'analyzer': u'ik_max_word',
                        u'type': u'text'
                    }
                }
            }
        }
    }
}

說明索引的確是按template自動建立了。

更深入的探討,如果我們建立一個新的模板,通配test*的模型的話,對於test_001這樣的索引,又會怎樣呢?

t2 = {
    u'aliases': {},
    u'mappings': {
        u'_default_': {
            u'_source': {
                u'enabled': False
            },
            u'properties': {
                u"author": {u"type": u'keyword'}
            }
        }
    },
    u'order': 1,
    u'settings': {u'index': {u'number_of_shards': u'1'}},
    u'template': u'test*'
}
es.indices.put_template(name='test_sub', body=t2, create=True)

這個時候再建立一個新的索引test_002, 它的mapping會這樣:

{
    u'test_003': {
        u'mappings': {
            u'_default_': {
                u'_source': {
                    u'enabled': False
                },
                u'properties': {
                    u'author': {
                        u'type': u'keyword'
                    },
                    u'title': {
                        u'analyzer': u'ik_max_word',
                        u'type': u'text'
                    }
                }
            },
            u'doc': {
                u'_source': {
                    u'enabled': False
                },
                u'properties': {
                    u'author': {
                        u'type': u'keyword'
                    },
                    u'title': {
                        u'analyzer': u'ik_max_word',
                        u'type': u'text'
                    }
                }
            }
        }
    }
}

說明test和test_sub的模板同時應用到了test_002這個索引上了。但是這是沒有衝突的情況,如果我們修改test_sub的配置,新增跟test重名的title欄位,但是配置不同的話,又會怎麼樣呢?

t3 = {
    u'aliases': {},
    u'mappings': {
        u'_default_': {
            u'_source': {
                u'enabled': False
            },
            u'properties': {
                u"title": {u"type": u'keyword'}
            }
        }
    },
    u'order': 1,
    u'settings': {u'index': {u'number_of_shards': u'1'}},
    u'template': u'test*'
}
es.indices.put_template(name='test_sub', body=t3)

然後建立新的索引test_003, 直接報錯:

TransportError(400, u'mapper_parsing_exception', u'Mapping definition for [title] has unsupported parameters:  [search_analyzer : ik_max_word] [analyzer : ik_max_word]')

看來似乎es還不支援子模板欄位重名的情況。。。我用es的版本是5.4.3,不知道將來會不會有改動。

相關文章