forked from optionalg/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.psgi
117 lines (98 loc) · 2.93 KB
/
search.psgi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/env perl
use strict;
use warnings;
use Encode qw(encode_utf8);
use Plack::Request;
use Plack::Builder;
use Plack::Response;
use Search::Elasticsearch;
use FindBin;
use lib "$FindBin::RealBin/lib";
use ES::Util qw(run);
chdir($FindBin::RealBin);
our $host = 'localhost:9200';
our $es = Search::Elasticsearch->new( nodes => $host );
our $JSON = $es->transport->serializer;
builder {
mount '/search/' => \&doc_search;
mount '/status' => \&status;
};
#===================================
sub status {
#===================================
my $req = Plack::Request->new( shift() );
my $result
= eval { run(qw(git show --shortstat _index)); }
|| $@
|| 'Unknown error';
return [ 200, [ 'Content-Type' => 'text/plain' ], [$result] ];
}
#===================================
sub doc_search {
#===================================
my $env = shift;
my $req = Plack::Request->new($env);
my $q = $req->param('q');
my $callback = $req->param('callback');
my $ref = $env->{"HTTP_REFERER"} || '';
$ref =~ s{/index.html[^/]*$}{};
my ( $book, $version );
if ( $ref =~ m{^https?:https://[^/]+/guide/(.+?)(?:/([^/]+)/([^/]+))?$} ) {
$book = $1;
$version = $2;
}
$version ||= 'current';
my $query = {
filtered => {
query => {
multi_match => {
query => $q,
#type => 'cross_fields',
fields => [
'title^2', 'title.content',
'title.shingles', 'title.ngrams',
'text', 'text.content',
'text.shingles', 'text.ngrams',
],
minimum_should_match => '80%',
}
},
filter =>
{ bool => { must => [ { term => { version => $version } } ] } }
},
};
if ($book) {
push @{ $query->{filtered}{filter}{bool}{must} },
{ term => { "book.raw" => $book } };
}
else {
$query = {
function_score => {
query => $query,
functions => [
{ filter => {
term =>
{ "book.raw" => 'en/elasticsearch/reference' }
},
boost_factor => 1.5
}
]
}
};
}
my $result = $es->search(
index => 'docs',
_source => [ 'title', 'abbr', 'url', 'path', 'book' ],
body => {
query => $query,
size => 10,
},
);
for ( @{ $result->{hits}{hits} } ) {
$_->{fields} = delete $_->{_source};
}
my $json = $JSON->encode($result);
$json = $callback . '(' . $json . ')'
if $callback;
return [ 200, [ 'Content-Type' => 'application/json' ], [$json] ];
}