1Lucy::Docs::Tutorial::QUuseerryOCbojnetcrtisbLTuuutcteyod:r:iPDaeolrc(ls3:)D:oTcuutmoernitaalt:i:oQnueryObjectsTutorial(3)
2
3
4

NAME

6       Lucy::Docs::Tutorial::QueryObjectsTutorial - Use Query objects instead
7       of query strings.
8

DESCRIPTION

10       Until now, our search app has had only a single search box.  In this
11       tutorial chapter, we’ll move towards an “advanced search” interface, by
12       adding a “category” drop-down menu.  Three new classes will be
13       required:
14
15       •   QueryParser - Turn a query string into a Query object.
16
17       •   TermQuery - Query for a specific term within a specific field.
18
19       •   ANDQuery - “AND” together multiple Query objects to produce an
20           intersected result set.
21
22   Adaptations to indexer.pl
23       Our new “category” field will be a StringType field rather than a
24       FullTextType field, because we will only be looking for exact matches.
25       It needs to be indexed, but since we won’t display its value, it
26       doesn’t need to be stored.
27
28           my $cat_type = Lucy::Plan::StringType->new( stored => 0 );
29           $schema->spec_field( name => 'category', type => $cat_type );
30
31       There will be three possible values: “article”, “amendment”, and
32       “preamble”, which we’ll hack out of the source file’s name during our
33       "parse_file" subroutine:
34
35           my $category
36               = $filename =~ /art/      ? 'article'
37               : $filename =~ /amend/    ? 'amendment'
38               : $filename =~ /preamble/ ? 'preamble'
39               :                           die "Can't derive category for $filename";
40           return {
41               title    => $title,
42               content  => $bodytext,
43               url      => "/us_constitution/$filename",
44               category => $category,
45           };
46
47   Adaptations to search.cgi
48       The “category” constraint will be added to our search interface using
49       an HTML “select” element (this routine will need to be integrated into
50       the HTML generation section of search.cgi):
51
52           # Build up the HTML "select" object for the "category" field.
53           sub generate_category_select {
54               my $cat = shift;
55               my $select = qq|
56                 <select name="category">
57                   <option value="">All Sections</option>
58                   <option value="article">Articles</option>
59                   <option value="amendment">Amendments</option>
60                 </select>|;
61               if ($cat) {
62                   $select =~ s/"$cat"/"$cat" selected/;
63               }
64               return $select;
65           }
66
67       We’ll start off by loading our new modules and extracting our new CGI
68       parameter.
69
70           use Lucy::Search::QueryParser;
71           use Lucy::Search::TermQuery;
72           use Lucy::Search::ANDQuery;
73
74           ...
75
76           my $category = decode( "UTF-8", $cgi->param('category') || '' );
77
78       QueryParser’s constructor requires a “schema” argument.  We can get
79       that from our IndexSearcher:
80
81           # Create an IndexSearcher and a QueryParser.
82           my $searcher = Lucy::Search::IndexSearcher->new(
83               index => $path_to_index,
84           );
85           my $qparser  = Lucy::Search::QueryParser->new(
86               schema => $searcher->get_schema,
87           );
88
89       Previously, we have been handing raw query strings to IndexSearcher.
90       Behind the scenes, IndexSearcher has been using a QueryParser to turn
91       those query strings into Query objects.  Now, we will bring QueryParser
92       into the foreground and parse the strings explicitly.
93
94           my $query = $qparser->parse($q);
95
96       If the user has specified a category, we’ll use an ANDQuery to join our
97       parsed query together with a TermQuery representing the category.
98
99           if ($category) {
100               my $category_query = Lucy::Search::TermQuery->new(
101                   field => 'category',
102                   term  => $category,
103               );
104               $query = Lucy::Search::ANDQuery->new(
105                   children => [ $query, $category_query ]
106               );
107           }
108
109       Now when we execute the query…
110
111           # Execute the Query and get a Hits object.
112           my $hits = $searcher->hits(
113               query      => $query,
114               offset     => $offset,
115               num_wanted => $page_size,
116           );
117
118       … we’ll get a result set which is the intersection of the parsed query
119       and the category query.
120
121   Using TermQuery with full text fields
122       When querying full text fields, the easiest way is to create query
123       objects using QueryParser. But sometimes you want to create TermQuery
124       for a single term in a FullTextType field directly. In this case, we
125       have to run the search term through the field’s analyzer to make sure
126       it gets normalized in the same way as the field’s content.
127
128           sub make_term_query {
129               my ($field, $term) = @_;
130
131               my $token;
132               my $type = $schema->fetch_type($field);
133
134               if ( $type->isa('Lucy::Plan::FullTextType') ) {
135                   # Run the term through the full text analysis chain.
136                   my $analyzer = $type->get_analyzer;
137                   my $tokens   = $analyzer->split($term);
138
139                   if ( @$tokens != 1 ) {
140                       # If the term expands to more than one token, or no
141                       # tokens at all, it will never match a token in the
142                       # full text field.
143                       return Lucy::Search::NoMatchQuery->new;
144                   }
145
146                   $token = $tokens->[0];
147               }
148               else {
149                   # Exact match for other types.
150                   $token = $term;
151               }
152
153               return Lucy::Search::TermQuery->new(
154                   field => $field,
155                   term  => $token,
156               );
157           }
158
159   Congratulations!
160       You’ve made it to the end of the tutorial.
161
162   See Also
163       For additional thematic documentation, see the Apache Lucy Cookbook.
164
165       ANDQuery has a companion class, ORQuery, and a close relative,
166       RequiredOptionalQuery.
167
168
169
170perl v5.36.0                     L2u0c2y3:-:0D1o-c2s0::Tutorial::QueryObjectsTutorial(3)
Impressum