1: <?php
2: namespace elasticsearch;
3:
4: 5: 6: 7: 8: 9: 10:
11: class Searcher{
12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
23: public static function search($search, $pageIndex = 0, $size = 10, $facets = array(), $sortByDate = false){
24: $args = self::_buildQuery($search, $facets);
25:
26: if(empty($args) || (empty($args['query']) && empty($args['facets']))){
27: return array(
28: 'total' => 0,
29: 'ids' => array(),
30: 'facets' => array()
31: );
32: }
33:
34: return self::_query($args, $pageIndex, $size, $sortByDate);
35: }
36:
37: 38: 39:
40: public static function _query($args, $pageIndex, $size, $sortByDate = false){
41: $query =new \Elastica\Query($args);
42: $query->setFrom($pageIndex * $size);
43: $query->setSize($size);
44: $query->setFields(array('id'));
45:
46: Config::apply_filters('searcher_query', $query);
47:
48: try{
49: $index = Indexer::_index(false);
50:
51: $search = new \Elastica\Search($index->getClient());
52: $search->addIndex($index);
53:
54: if($sortByDate){
55: $query->addSort(array('post_date' => 'desc'));
56: }else{
57: $query->addSort('_score');
58: }
59:
60: Config::apply_filters('searcher_search', $search);
61:
62: $results = $search->search($query);
63:
64: return self::_parseResults($results);
65: }catch(\Exception $ex){
66: error_log($ex);
67:
68: return null;
69: }
70: }
71:
72: 73: 74:
75: public static function _parseResults($response){
76: $val = array(
77: 'total' => $response->getTotalHits(),
78: 'facets' => array(),
79: 'ids' => array()
80: );
81:
82: foreach($response->getFacets() as $name => $facet){
83: if(isset($facet['terms'])){
84: foreach($facet['terms'] as $term){
85: $val['facets'][$name][$term['term']] = $term['count'];
86: }
87: }
88:
89: if(isset($facet['ranges'])){
90: foreach($facet['ranges'] as $range){
91: $from = isset($range['from']) ? $range['from'] : '';
92: $to = isset($range['to']) ? $range['to'] : '';
93:
94: $val['facets'][$name][$from . '-' . $to] = $range['count'];
95: }
96: }
97: }
98:
99: foreach($response->getResults() as $result){
100: $val['ids'][] = $result->getId();
101: }
102:
103: return Config::apply_filters('searcher_results', $val, $response);
104: }
105:
106: 107: 108:
109: public static function _buildQuery($search, $facets = array()){
110: global $blog_id;
111:
112: $search = str_ireplace(array(' and ', ' or '), array(' AND ', ' OR '), $search);
113:
114: $fields = array();
115: $musts = array();
116: $filters = array();
117:
118: foreach(Config::taxonomies() as $tax){
119: if($search){
120: $score = Config::score('tax', $tax);
121:
122: if($score > 0){
123: $fields[] = "{$tax}_name^$score";
124: }
125: }
126:
127: self::_filterBySelectedFacets($tax, $facets, 'term', $musts, $filters);
128: }
129:
130: $args = array();
131:
132: $numeric = Config::option('numeric');
133:
134: $exclude = Config::apply_filters('searcher_query_exclude_fields', array('post_date'));
135:
136: foreach(Config::fields() as $field){
137: if(in_array($field, $exclude)){
138: continue;
139: }
140:
141: if($search){
142: $score = Config::score('field', $field);
143:
144: if($score > 0){
145: $fields[] = "$field^$score";
146: }
147: }
148:
149: if(isset($numeric[$field]) && $numeric[$field]){
150: $ranges = Config::ranges($field);
151:
152: if(count($ranges) > 0 ){
153: self::_filterBySelectedFacets($field, $facets, 'range', $musts, $filters, $ranges);
154: }
155: }
156: }
157:
158: if(count($fields) > 0){
159: $qs = array(
160: 'fields' => $fields,
161: 'query' => $search
162: );
163:
164: $fuzzy = Config::option('fuzzy');
165:
166: if($fuzzy && strpos($search, "~") > -1){
167: $qs['fuzzy_min_sim'] = $fuzzy;
168: }
169:
170: $qs = Config::apply_filters('searcher_query_string', $qs);
171:
172: $args['query']['query_string'] = $qs;
173: }
174:
175: if(count($filters) > 0){
176: $args['filter']['bool']['should'] = $filters;
177: }
178:
179: if(count($musts) > 0){
180: $args['query']['bool']['must'] = $musts;
181: }
182:
183: $args['filter']['bool']['must'][] = array( 'term' => array( 'blog_id' => $blog_id ) );
184:
185: $args = Config::apply_filters('searcher_query_pre_facet_filter', $args);
186:
187:
188: foreach(Config::facets() as $facet){
189: $args['facets'][$facet]['terms']['field'] = $facet;
190: $args['facets'][$facet]['facet_filter'] = array( 'term' => array( 'blog_id' => $blog_id ) );
191: }
192:
193: if(is_array($numeric)){
194: foreach(array_keys($numeric) as $facet){
195: $ranges = Config::ranges($facet);
196:
197: if(count($ranges) > 0 ){
198: $args['facets'][$facet]['range'][$facet] = array_values($ranges);
199: $args['facets'][$facet]['facet_filter'] = array( 'term' => array( 'blog_id' => $blog_id ) );
200: }
201: }
202: }
203:
204: return Config::apply_filters('searcher_query_post_facet_filter', $args);
205: }
206:
207: 208: 209:
210: public static function _filterBySelectedFacets($name, $facets, $type, &$musts, &$filters, $translate = array()){
211: if(isset($facets[$name])){
212: $output = &$musts;
213:
214: $facets = $facets[$name];
215:
216: if(!is_array($facets)){
217: $facets = array($facets);
218: }
219:
220: foreach($facets as $operation => $facet){
221: if(is_string($operation) && $operation == 'or'){
222:
223: $output = &$filters;
224: }
225:
226: if(is_array($facet)){
227: foreach($facet as $value){
228: $output[] = array( $type => array( $name => isset($translate[$value]) ? $translate[$value] : $value ));
229: }
230:
231: continue;
232: }
233:
234: $output[] = array( $type => array( $name => isset($translate[$facet]) ? $translate[$facet] : $facet ));
235: }
236: }
237: }
238: }
239: ?>
240: