http://my.oschina.net/u/730537/blog/288703
这是初始化创建index和mapping的代码:
$elasticaClient = new \Elastica\Client(array('host'=>'localhost','port'=>9200));
// Load index
$elasticaIndex = $elasticaClient->getIndex('links');
// Create the index new
// 创建index的参数自行参见官网,就不一一解释了
$elasticaIndex->create(
array(
'number_of_shards' => 4,
'number_of_replicas' => 1,
'analysis' => array(
'analyzer' => array(
'indexAnalyzer' => array(
'type' => 'custom',
'tokenizer' => 'standard',
'filter' => array('lowercase', 'mySnowball')
),
'searchAnalyzer' => array(
'type' => 'custom',
'tokenizer' => 'standard',
'filter' => array('standard', 'lowercase', 'mySnowball')
)
),
'filter' => array(
'mySnowball' => array(
'type' => 'snowball',
'language' => 'German'
)
)
)
),
true
);
//创建media的mapping,作为父级
$mediaType = $elasticaIndex->getType('media');
// Define mapping
$mapping = new \Elastica\Type\Mapping();
$mapping->setType($mediaType);
$mapping->setParam('index_analyzer', 'indexAnalyzer');
$mapping->setParam('search_analyzer', 'searchAnalyzer');
// Define boost field
$mapping->setParam('_boost', array('name' => '_boost', 'null_value' => 1.0));
// Set mapping
// 定义media的字段和属性
$mapping->setProperties(array(
'id' => array('type' => 'string', 'include_in_all' => FALSE),
'media_name' => array('type' => 'string', 'include_in_all' => TRUE),
'tstamp' => array('type' => 'date', 'include_in_all' => FALSE),
'language' => array('type' => 'integer', 'include_in_all' => FALSE),
'_boost' => array('type' => 'float', 'include_in_all' => FALSE)
));
// Send mapping to type
// 保存media的mapping
$mapping->send();
//创建question的mapping,父级为media
$questionType = $elasticaIndex->getType('question');
// Define mapping
$mapping = new \Elastica\Type\Mapping();
$mapping->setType($questionType);
$mapping->setParam('index_analyzer', 'indexAnalyzer');
$mapping->setParam('search_analyzer', 'searchAnalyzer');
// Define boost field
$mapping->setParam('_boost', array('name' => '_boost', 'null_value' => 1.0));
// Set mapping
// question的字段和属性
$mapping->setProperties(array(
'id' => array('type' => 'string', 'include_in_all' => FALSE),
'level_one' => array('type' => 'integer', 'include_in_all' => FALSE),
'level_two' => array('type' => 'integer', 'include_in_all' => FALSE),
'level_thr' => array('type' => 'integer', 'include_in_all' => FALSE),
'top_level' => array('type' => 'string', 'include_in_all' => FALSE),
'cat_id' => array('type' => 'integer', 'include_in_all' => FALSE),
'quest_hash' => array('type' => 'string', 'include_in_all' => TRUE),
'content' => array('type' => 'string', 'include_in_all' => TRUE),
'view_num' => array('type' => 'integer', 'include_in_all' => FALSE),
'like_num' => array('type' => 'integer', 'include_in_all' => FALSE),
'_boost' => array('type' => 'float', 'include_in_all' => FALSE)
));
$mapping->setParent("media");//指定question的父类
// Send mapping to type
// 保存question的mapping
$mapping->send();
上面虽然是PHP代码,但是最终生成的也是一个url请求。
下面说搜索,搜索的话ES是通过query、filter等来处理的,query里面有很多不同的方式,参见:http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-queries.html,filter也是,参见http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-filters.html
这里搜索是这样的,根据media的media_name做query_string搜索,然后对media进行has_child的filter搜索,has_child搜索内使用boolAnd的filter来筛选。
下面是搜索的代码:
$query = new \Elastica\Query();
if (!empty($input['key'])) {
//针对media的media_name字段设置QueryString查询
$elasticaQueryString = new \Elastica\Query\QueryString();
$elasticaQueryString->setFields(array("media.media_name"));
$elasticaQueryString->setQuery($input['key']);
//
$query->setQuery($elasticaQueryString);
}else {
$query->setQuery(new MatchAll()); //命中全部纪录
}
$language_bool = false;
$elasticaFilterAnd = new \Elastica\Filter\BoolAnd();
//language也是针对media,设置BoolAnd查询
if (isset($input['language']) && !empty($input['language'])) {
$filterl1 = new \Elastica\Filter\Term();
$filterl1->setTerm('language', intval($input['language']));
$elasticaFilterAnd->addFilter($filterl1);
$language_bool = true;
}
//
//对子集进行筛选查询,使用has_child
$subFilterAnd = new \Elastica\Filter\BoolAnd();
$bool = false;
// 一级分类条件
if (isset($input['level_one']) && !empty($input['level_one'])) {
$filterl1 = new \Elastica\Filter\Term();
$filterl1->setTerm('level_one', intval($input['level_one']));
$subFilterAnd->addFilter($filterl1);
$bool = true;
}
// 二级分类条件
if (isset($input['level_two']) && !empty($input['level_two'])) {
$filterl1 = new \Elastica\Filter\Term();
$filterl1->setTerm('level_two', intval($input['level_two']));
$subFilterAnd->addFilter($filterl1);
$bool = true;
}
// 三级分类条件
if (isset($input['level_thr']) && !empty($input['level_thr'])) {
$filterl1 = new \Elastica\Filter\Term();
$filterl1->setTerm('level_thr', intval($input['level_thr']));
$subFilterAnd->addFilter($filterl1);
$bool = true;
}
// 直接指定分类ID查询
if (isset($input['cat_id']) && !empty($input['cat_id'])) {
$filterl1 = new \Elastica\Filter\Term();
$filterl1->setTerm('cat_id', intval($input['cat_id']));
$subFilterAnd->addFilter($filterl1);
$bool = true;
}
// 分类属性查询
if (isset($input['top_level']) && !empty($input['top_level'])) {
$filterl1 = new \Elastica\Filter\Term();
$filterl1->setTerm('top_level', $input['top_level']);
$subFilterAnd->addFilter($filterl1);
$bool = true;
}
if($bool){
// 声明一个查询,用于放入子查询
$subQuery = new \Elastica\Query();
// 使用filteredquery,融合query和filter
$filteredQuery = new \Elastica\Query\Filtered(new MatchAll(),$subFilterAnd);
// 添加filterquery到子查询
$subQuery->setQuery($filteredQuery);
// 声明hasChildFilter,声明的时候就指定子查询的内容,指定查询的子表(也就是TYPE)为question
$filterHasChild = new \Elastica\Filter\HasChild($subQuery,"question");
// 将拥有子类查询增加到父级查询的filter中
$elasticaFilterAnd->addFilter($filterHasChild);
}
if($bool || $language_bool){
// 将filter增加到父查询汇中
$query->setFilter($elasticaFilterAnd);
}
//
//
$query->setFrom($start); // Where to start?
$query->setLimit($limit); // How many?
//
//Search on the index.
$elasticaResultSet = $elasticaIndex->search($query);
在处理过程中,感谢之前的哥们留下的代码,至少不是摸瞎。感谢同事搞的谷歌搜索,一般人我不告诉他,大家可以去试试 另客网,首页的搜索框里面,选择谷歌。
http://www.links123.com/
部分借鉴来自于这里:http://www.spacevatican.org/2012/6/3/fun-with-elasticsearch-s-children-and-nested-documents/