Elasticsearch 入门教程 – mget多文档查询

 标识符(ids)过滤器:

 需要过滤出若干指定_id的文档,可使用标识符过滤器(ids)

GET /ecommerce/product/_search
{
  "query": {
     "ids":{
                    "values":[1,2,6,7]
     }
  }
}

{
    "query": {
        "filtered":{
            "filter":{
                "ids":{
                    "values":[1,2,6,7]
                }
            }
        }   
    }
}
String id1 = "1";
String id2 = "2";
QueryBuilder qb = QueryBuilders.idsQuery("article").addIds(id1,id2);

  需注意的是:指定的标识符是文档的_id,为文档唯一标识。不同于自己指定的id字段。

multi Get

多字段查询可以设置多个文档查询条件,每个查询条件在结构上都比较类似:

GET /_mget
{

    "docs" : [

        {

            "_index" : "test",

            "_type" : "type",

            "_id" : "1"

        },

        {

            "_index" : "test",

            "_type" : "type",

            "_id" : "2"

        }

    ]

}

Java客户端代码:

MultiGetResponse multiGetResponse = client.prepareMultiGet()
			        .add("ecommerce", "product", "1")
			        .add("ecommerce", "product", "1","2", "3")
			        .get();
		
		 for (MultiGetItemResponse itemResponse : multiGetResponse) {
			GetResponse response = itemResponse.getResponse();
			if (response.isExists()) {
				String sourceAsString = response.getSourceAsString();
				System.out.println(sourceAsString);
			}
		 }

当然,在查询条件中,body中_index字段也可以放在查询字符串中:

GET /test/_mget
{

    "docs" : [

        {

            "_type" : "type",

            "_id" : "1"

        },

        {

            "_type" : "type",

            "_id" : "2"

        }

    ]

}

对于type也是一样:

GET /test/type/_mget
{

    "docs" : [

        {

            "_id" : "1"

        },

        {

            "_id" : "2"

        }

    ]

}

如果索引和类型都放在查询URL中,那么字段ID就可以放在一个数组中:

GET /test/type/_mget
{

    "ids" : ["1", "2"]

}

type可选

mget查询中类型type是可选的。如果设置_all或者不设置,就会匹配所有的类型,那么仅仅会返回第一个匹配的文档。

但是如果没有设置type,然后查询的id里面又出现两个一样的id,就会返回第一次匹配的文档两次:

GET /test/_mget
{

    "ids" : ["1", "1"]

}

因此如果想要查询到不同类型的id,就需要指定类型名称:

GET /test/_mget/
{  "docs" : [
        {            "_type":"typeA",            "_id" : "1"
        },
        {            "_type":"typeB",            "_id" : "1"
        }
    ]
}

_source过滤

默认_source字段会返回所有的内容,你也可以通过_source进行过滤。比如使用_source,_source_include,_source_exclude.
比如:

GET /_mget
{

    "docs" : [

        {

            "_index" : "test",

            "_type" : "type",

            "_id" : "1",

            "_source" : false

        },

        {

            "_index" : "test",

            "_type" : "type",

            "_id" : "2",

            "_source" : ["field3", "field4"]

        },

        {

            "_index" : "test",

            "_type" : "type",

            "_id" : "3",

            "_source" : {

                "include": ["user"],

                "exclude": ["user.location"]

            }

        }

    ]

}

路由

在mget查询中也会涉及到路由的问题。可以在url中设置默认的路由,然后在Body中修改:

GET /_mget?routing=key1
{

    "docs" : [

        {

            "_index" : "test",

            "_type" : "type",

            "_id" : "1",

            "_routing" : "key2"

        },

        {

            "_index" : "test",

            "_type" : "type",

            "_id" : "2"

        }

    ]

}

在上面的例子中,test/type/1按照key2这个路由锁定分片进行查询;test/type/2按照key1这个路由锁定分片进行查询。

实际演练

首先创建两个文档:

POST /test/_mget?pretty
{"ids":["1"]}

POST /test/testb/1?pretty
{"name":"b","age":122}

如果不指定type,那么返回的仅仅是一个最先匹配的结果:

GET /test/_mget?pretty 
{
   "ids":["1"]
}

如果指定了重复的id,则返回的是多次第一次匹配的文档:

GET /test/type/_mget?pretty 
{
   "ids":["1"]
}

如果指定了类型,再去查询,则返回的是各自的id:

mget的重要性

   可以说mget是很重要的,一般来说,在进行查询的时候,如果一次性要查询多条数据的话,那么一定要用batch批量操作的api

尽可能减少网络开销次数,可能可以将性能提升数倍,甚至数十倍,非常非常之重要

发表评论