Use commit timestamps for ElasticSearch and sort on last commit time.
[phorkie.git] / src / phorkie / Database / Adapter / Elasticsearch / Search.php
1 <?php
2 namespace phorkie;
3
4 class Database_Adapter_Elasticsearch_Search implements Database_ISearch
5 {
6     protected static $sortMap = array(
7         'id' => array('id', 'asc'),
8         'crdate' => array('crdate', 'desc'),
9         'modate' => array('modate', 'desc'),
10         'tstamp' => array('tstamp', 'desc'),
11     );
12
13     public function __construct()
14     {
15         $this->searchInstance = $GLOBALS['phorkie']['cfg']['elasticsearch'];
16     }
17
18     /**
19      * List all repositories
20      *
21      * @param integer $page    Page of search results, starting with 0
22      * @param integer $perPage Number of results per page
23      * @param string  $sort    Sort order. Allowed values:
24      *                         - id     - repository id
25      *                         - crdate - creation date
26      *                         - modate - modification date
27      *                         - tstamp - last index date
28      *
29      * @return Search_Result Search result object
30      */
31     public function listAll($page = 0, $perPage = 10, $sort = 'id', $sortOrder = null)
32     {
33         list($sortField, $orderField) = $this->getSortField($sort, $sortOrder);
34         $r = new Database_Adapter_Elasticsearch_HTTPRequest(
35             $this->searchInstance . 'repo/_search',
36             \HTTP_Request2::METHOD_GET
37         );
38         $r->setBody(
39             json_encode(
40                 (object)array(
41                     'from'  => $page * $perPage,
42                     'size'  => $perPage,
43                     'sort'  => array(
44                         $sortField => $orderField
45                     ),
46                     'query' => (object)array(
47                         'match_all' => (object)array()
48                     ),
49                 )
50             )
51         );
52         $httpRes = $r->send();
53         $jRes = json_decode($httpRes->getBody());
54         if (isset($jRes->error)) {
55             throw new Exception(
56                 'Search exception: ' . $jRes->error, $jRes->status
57             );
58         }
59
60         $sres = new Search_Result();
61         $sres->results = $jRes->hits->total;
62         $sres->page    = $page;
63         $sres->perPage = $perPage;
64
65         foreach ($jRes->hits->hits as $hit) {
66             $r = new Repository();
67             $r->loadById($hit->_source->id);
68             $r->crdate = strtotime($hit->_source->crdate);
69             $r->modate = strtotime($hit->_source->modate);
70             $sres->repos[] = $r;
71         }
72
73         return $sres;
74     }
75
76
77     /**
78      * Search for a given term and return repositories that contain it
79      * in their description, file names or file content
80      *
81      * @param string  $term    Search term
82      * @param integer $page    Page of search results, starting with 0
83      * @param integer $perPage Number of results per page
84      *
85      * @return Search_Result Search result object
86      */
87     public function search($term, $page = 0, $perPage = 10)
88     {
89         $r = new Database_Adapter_Elasticsearch_HTTPRequest(
90             $this->searchInstance . 'repo/_search',
91             \HTTP_Request2::METHOD_GET
92         );
93         $r->setBody(
94             json_encode(
95                 (object)array(
96                     'from' => $page * $perPage,
97                     'size' => $perPage,
98                     'query' => (object)array(
99                         'bool' => (object)array(
100                             'should' => array(
101                                 (object)array(
102                                     'query_string' => (object)array(
103                                         'query' => $term,
104                                         'default_operator' => 'AND'
105                                     ),
106                                 ),
107                                 (object)array(
108                                     'has_child' => (object)array(
109                                         'type'         => 'file',
110                                         'query' => (object)array(
111                                             'query_string' => (object)array(
112                                                 'query' => $term,
113                                                 'default_operator' => 'AND'
114                                             )
115                                         )
116                                     )
117                                 )
118                             )
119                         )
120                     )
121                 )
122             )
123         );
124         $httpRes = $r->send();
125         $jRes = json_decode($httpRes->getBody());
126         if (isset($jRes->error)) {
127             throw new Exception(
128                 'Search exception: ' . $jRes->error, $jRes->status
129             );
130         }
131
132         $sres = new Search_Result();
133         $sres->results = $jRes->hits->total;
134         $sres->page    = $page;
135         $sres->perPage = $perPage;
136
137         foreach ($jRes->hits->hits as $hit) {
138             $r = new Repository();
139             //FIXME: error handling. what about deleted repos?
140             $r->loadById($hit->_source->id);
141             $sres->repos[] = $r;
142         }
143
144         return $sres;
145     }
146
147     protected function getSortField($sort, $sortOrder)
148     {
149         if (!isset(self::$sortMap[$sort])) {
150             throw new Exception('Invalid sort parameter: ' . $sort);
151         }
152         if ($sortOrder !== 'asc' && $sortOrder !== 'desc') {
153             throw new Exception('Invalid sortOrder parameter: ' . $sortOrder);
154         }
155
156         $data = self::$sortMap[$sort];
157         if ($sortOrder !== null) {
158             $data[1] = $sortOrder;
159         }
160         return $data;
161     }
162 }
163
164 ?>