5 分钟内学会使用搜索利器 Elastic Search - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
CodingNET
V2EX    Elasticsearch

5 分钟内学会使用搜索利器 Elastic Search

  •  2
     
  •   CodingNET 2015-08-19 10:56:05 +08:00 7789 次点击
    这是一个创建于 3706 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本文简要介绍搜索利器 Elastic Search ,让你在 5 分钟内学会使用它。

    安装

    如果你有 linux ,并且恰好也有 docker , 那么请运行如下命令:

    sudo docker run -d -p 9200:9200 -p 9300:9300 elasticsearch 

    你要是看到一串 id , 恭喜你, 你已经有了自己的搜索了!就是这么简单!

    我们来验证一下搜索服务:

    ubuntu:~$ curl localhost:9200 { "status" : 200, "name" : "Adonis", "cluster_name" : "elasticsearch", "version" : { "number" : "1.7.1", "build_hash" : "b88f43fc40b0bcd7f173a1f9ee2e97816de80b19", "build_timestamp" : "2015-07-29T09:54:16Z", "build_snapshot" : false, "lucene_version" : "4.10.4" }, "tagline" : "You Know, for Search" } 

    返回值 200 !你成功了!这个结果除了告诉你 Elastic Search 已经启动好之外,还显示了版本号, build 信息, lucene 版本等信息。

    如果你不用 Linux 或者 Docker ,放心,情况也不复杂。首先你需要 Java ,然后去官网下载,解压,运行既可。

    使用

    Elastic Search 的初级功能十分易用。 Restful 请求就可以完成一切操作。所以接下来的体验,你只需要一个命令行即可,但是为了直观方便,你也可以选择官方推荐的 Marvel 或者 Postman

    相信很多人都是吃货,下面,我用中国第九大菜系食堂菜作为搜索的原数据演示 Elastic Search 的用法。

    插入数据

    首先来一道勉强正常的菜,苹果炖牛肉。

    ubuntu:~$ curl -XPOST localhost:9200/food/canteen?pretty -d '{title: "苹果炖牛肉", source: "sjtu"}' { "_index" : "food", "_type" : "canteen", "_id" : "AU8HEQxfW68mQc8rk4AS", "_version" : 1, "created" : true } 

    有点迷糊?那来稍微介绍一点背景知识,看看上面的命令都做了啥。

    Elastic Search 使用 document 方式存储, 类似 MongoDB 。它不仅高效而且分布式扩展性极佳,基于赫赫有名的 Lucene 搭建,在搜索界的地位就如同杰伦小公举在歌坛的地位一般。很多人可能有关系型数据库开发的经验,下面来张 Elastic Search 和 MySQL 的术语类比图,帮助理解。

    MySQL Elastic Search
    Database Index
    Table Type
    Row Document
    Column Field
    Schema Mappping
    Index Everything Indexed by default
    SQL Query DSL

    上面例子中,localhost:9200是服务地址, Elastic Search 默认利用 9200 作为 Rest 服务的端口, 9300 作为内部通信接口和 Java 客户端接口。food是 index ,canteen是 type ,里面的数据形成 document 。值得注意的是,跟其他 NoSQL 数据库一样, Schema 不需要预先定义,直接插入数据即可, Elastic Search 会智能地分析每个 Field 的值并自动建立索引。每个 document 都有一个 id ,如果不指定则会自动生成。可以看到插入成功之后,生成了"_id" : "AU8HEQxfW68mQc8rk4AS"。插入命令使用 Post 请求,方便使用和测试。

    另外,在上面的例子中,我加入了?pretty主要是让结果的 json 显示更好看。

    获取数据

    虽然数据已经存好了,但是没有直接取到,总是心有不安,下面这条命令即可以查看数据:

    ubuntu:~$ curl -XGET localhost:9200/food/canteen/AU8HEQxfW68mQc8rk4AS?pretty { "_index" : "food", "_type" : "canteen", "_id" : "AU8HEQxfW68mQc8rk4AS", "_version" : 1, "found" : true, "_source":{title: "苹果炖牛肉", source: "sjtu"} } 

    可以看到,请求改为了GET,请求形式为/index/type/id

    更新数据

    再来一道菜,番茄炒菠萝,用到我们刚才说的POST请求。

    ubuntu:~$ curl -XPOST localhost:9200/food/canteen?pretty -d '{title: "番茄炒菠萝", source: "sjtu"}' { "_index" : "food", "_type" : "canteen", "_id" : "AU8HQW0-W68mQc8rk4Ab", "_version" : 1, "created" : true } 

    等等,这道菜是武汉大学的,看来我们得更新一下source。也许聪明的你已经猜到,发个PUT请求就可以搞定了。

    ubuntu:~$ curl -XPUT localhost:9200/food/canteen/AU8HQW0-W68mQc8rk4Ab?pretty -d '{title: "番茄炒菠萝", source: "whu"}' { "_index" : "food", "_type" : "canteen", "_id" : "AU8HQW0-W68mQc8rk4Ab", "_version" : 2, "created" : false } 

    可以看到_version变成了 2 ,表示更新过了。再GET一下确认结果。

    ubuntu:~$ curl -XGET localhost:9200/food/canteen/AU8HQW0-W68mQc8rk4Ab?pretty { "_index" : "food", "_type" : "canteen", "_id" : "AU8HQW0-W68mQc8rk4Ab", "_version" : 2, "found" : true, "_source":{title: "番茄炒菠萝", source: "whu"} } 

    可以看到,_source,也就是插入的原始数据,确实改变了。

    删除数据

    继续来一道菜,月饼炒辣椒!

    ubuntu:~$ curl -XPOST localhost:9200/food/canteen?pretty -d '{title: "月饼炒辣椒", source: "fjnu"}' { "_index" : "food", "_type" : "canteen", "_id" : "AU8HRPoOW68mQc8rk4Ac", "_version" : 1, "created" : true } 

    算了,好像太丧心病狂了,对吃货的幼小心灵产生了暴击,我们还是把它删掉吧。

    ubuntu:~$ curl -XDELETE localhost:9200/food/canteen/AU8HRPoOW68mQc8rk4Ac?pretty { "found" : true, "_index" : "food", "_type" : "canteen", "_id" : "AU8HRPoOW68mQc8rk4Ac", "_version" : 2 } 

    GET验证一下是否真的被删除了。

    ubuntu:~$ curl -XGET localhost:9200/food/canteen/AU8HRPoOW68mQc8rk4Ac?pretty { "_index" : "food", "_type" : "canteen", "_id" : "AU8HRPoOW68mQc8rk4Ac", "found" : false } 

    显示"found" : false,可见删除确实成功了。

    搜索数据

    Elastic Search 支持相当复杂的搜索情形。像“有水果有肉有主食红黄白相间成粒状”这种可以把 MySQL 的检索虐得死去活来的查询, Elastic Search 可以轻松告诉你这应该是名菜“哈密瓜年糕牛肉粒”。下面看看最简单却很实用的搜索:查询所有值。

    ubuntu:~$ curl -XGET localhost:9200/food/canteen/_search?pretty { "took" : 1, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 2, "max_score" : 1.0, "hits" : [ { "_index" : "food", "_type" : "canteen", "_id" : "AU8HEQxfW68mQc8rk4AS", "_score" : 1.0, "_source":{tile: "苹果炖牛肉", source: "sjtu"} }, { "_index" : "food", "_type" : "canteen", "_id" : "AU8HQW0-W68mQc8rk4Ab", "_score" : 1.0, "_source":{title: "番茄炒菠萝", source: "whu"} } ] } } 

    可以看到,形如GET _search即可。结果会显示所有给定 index 和 type 下的 document 。hits下面包含找到的具体内容。_score表示相关程度,分数越高表示越相关,搜索引擎对于结果的排序都是通过类似的机制完成。
    再来一个简单地查询,查找sourcesjtu的菜。

    ubuntu:~$ curl -XGET localhost:9200/food/canteen/_search?pretty -d '{"query":{"match":{"source":"sjtu"}}}' { "took" : 35, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 1, "max_score" : 0.30685282, "hits" : [ { "_index" : "food", "_type" : "canteen", "_id" : "AU8HEQxfW68mQc8rk4AS", "_score" : 0.30685282, "_source":{title: "苹果炖牛肉", source: "sjtu"} } ] } } 

    这里用到了match query来搜索,可以看到_score的变化。

    结语

    本文对 Elastic Search 的使用作了最简单的介绍,适合新手入门。上述例子简单直观,命令可以直接运行,亲测有效。有兴趣的读者可以自己动手实践,加入更多诸如“糖宝炖骨头”这样的黑暗料理。

    全文: https://blog.coding.net/blog/elastic-search

    PS :

    Coding 在 V2EX 的 Social Integration 已上线,小伙伴们可以在 settings 添加自己的 Coding 地址啦!
    效果见: member/CodingNET

    20 条回复    2015-08-20 11:11:58 +08:00
    qinglangee
        1
    qinglangee  
       2015-08-19 11:05:38 +08:00
    Elastic Search 是什么
    andy12530
        2
    andy12530  
       2015-08-19 11:24:57 +08:00
    ES 的 query 串写起来,太费劲了
    wbsdty331
        3
    wbsdty331  
       2015-08-19 11:27:24 +08:00
    苹果炖牛肉笑飞
    tabris17
        4
    tabris17  
       2015-08-19 11:28:02 +08:00
    mapping 都没讲啊,这个离实战还差一点
    zkd8907
        5
    zkd8907  
       2015-08-19 15:45:04 +08:00
    苹果炖牛肉是什么鬼。。
    EPr2hh6LADWqRVH
        6
    EPr2hh6LADQWqRVH  
       2015-08-19 15:49:49 +08:00
    无视中文分词啊,这都行,真把这当软文了啊,不要为了写而写啊
    lijinma
        7
    lijinma  
       2015-08-19 16:07:26 +08:00
    哈哈,我觉得最基本的为什么使用 ES 都没讲,这才是最重要的。

    另外,中文 ik 分词啥的得提一提
    RIcter
        8
    RIcter  
       2015-08-19 17:38:09 +08:00 via iPhone
    ES 自的 HQ 插件很好用,完全不用操心。
    simodorg
        9
    simodorg  
       2015-08-19 17:58:10 +08:00 via iPhone
    好奇在这里除了他自己还有谁加了 coding 的账号...
    yakczh
        10
    yakczh  
       2015-08-19 18:00:29 +08:00
    跟 solr 相比,内存占用怎么样?
    tolbkni
        11
    tolbkni  
       2015-08-19 20:58:23 +08:00
    ES 的组合查询门槛有点高,不停翻文档才搞定
    cnZary
        12
    cnZary  
       2015-08-19 21:06:52 +08:00 via Android
    番茄炒菠萝好吃?
    anubiskong
        13
    anubiskong  
       2015-08-19 21:44:51 +08:00
    coding.net 写东西就这个水平吗?
    df4VW
        14
    df4VW  
       2015-08-20 00:24:50 +08:00
    @andy12530 现在已经好多了吧。。以前
    49
        15
    49  
       2015-08-20 07:35:32 +08:00 via Android
    @RIcter RR 都这么说了…那我肯定要去试试
    FastWood
        16
    FastWood  
       2015-08-20 08:16:16 +08:00
    感谢
    north521
        17
    north521  
       2015-08-20 09:03:57 +08:00
    很早就关注 es 了,用来替代 Lucene , but , es 的服务器要求 12G 以上内存,当时就吓软了
    lZl
        18
    lZl  
       2015-08-20 09:06:12 +08:00
    ES 也是用 Lucene ,替代也是替代 Solr 。。。
    nullcc
        19
    nullcc  
       2015-08-20 10:51:45 +08:00
    es 算是开源的全文搜索引擎里面比较容易入门的了,不过对内存要求太高
    master13
        20
    master13  
       2015-08-20 11:11:58 +08:00
    用 RESTful API 能实现搜索的功能。一般还需要一个“套”,让他好看一点 boss 不会喜欢看 JSON 数据的
    关于 nbsp;   帮助文档     自助推广系统     博客     API     FAQ     Solana     5602 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 07:52 PVG 15:52 LAX 00:52 JFK 03:52
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86