Class: Scrivito::ObjSearchEnumerator
- Inherits:
-
Object
- Object
- Scrivito::ObjSearchEnumerator
- Includes:
- Enumerable
- Defined in:
- app/cms/scrivito/obj_search_enumerator.rb,
app/cms/scrivito/obj_search_enumerator/batch.rb,
app/cms/scrivito/obj_search_enumerator/facet_query.rb,
app/cms/scrivito/obj_search_enumerator/batch_iterator.rb,
app/cms/scrivito/obj_search_enumerator/query_executor.rb
Overview
Provides an enumerator for iterating over the results of searches for CMS objects to retrieve instances of these objects. This is achieved through the Enumerable
mixin, which provides methods such as map
, select
or take
.
This enumerator is lazy. If, for example, you are looking for Objs whose object class is Publication
, and there are 93 objects in total, then enum.take(10) fetches the first 10 objects only, ignoring the other 83. This implies that repeatedly iterating over this enumerator causes the search results and the objects to be fetched again and again. If you want to get all objects at once, use enum.to_a
.
To start searching, use one of the Obj methods that return an ObjSearchEnumerator. The preferred way is to start with Obj.where or Obj.all.
Currently available fields and their values
:*
-
Searches all fields. This is only possible with the
contains
,contains_prefix
,refers_to
andlinks_to
operators. :id
-
Id of an Obj. This is a
string
field. :_path
-
Path of an Obj. This is a
string
field. :_name
-
Name of an Obj. This is a
string
field. :_obj_class
-
Object class of an Obj. This is a
string
field. :_permalink
-
Permalink of an Obj. This is a
string
field. :_created_at
-
The creation date of an Obj.
:_last_changed
-
Date of last change to an Obj.
- every
:custom_attribute
-
Custom attribute of an Obj. Note that depending on the attribute type (e.g. an
html
field), some operators cannot be applied.
Meta Data
If an Obj has a binary
attribute named blob
, the meta data of this attribute is searchable. For a full list of the available meta data attributes, see the documentation of the MetaDataCollection. The meta data attribute name needs to be prefixed with blob:
when searching for it. So, for example, when searching for the width, you need to specify the attribute name using blob:width
. Binary attributes other than blob
are not searchable.
Currently available operators
contains
and contains_prefix
These operators are intended for full text search of natural language texts. They are applicable to string
, stringlist
, enum
, multienum
and html
fields.
For contains
and contains_prefix
, the examples are based on the following field value: “Behind every cloud is another cloud.”
:contains
-
Searches for one or more whole words. Each word needs to be present.
Example subquery values:
✔ “behind cloud” (case insensitive)
✘ “behi clo” (not whole words)
✘ “behind everything” (second word does not match)
:contains_prefix
-
Searches for a word prefix.
Example subquery values:
✔ “Clou” (case insensitive)
✔ “Every” (case insensitive)
equals
The equals
operator is intended for programmatic comparisons of string and date values.
The operator has some limits with regard to string length. String values are only guaranteed to be considered if they are at most 1000 characters in length. String values of more than 1000 characters may be ignored by these operators.
For equals
, the examples are based on the following field value: “Some content.”
:equals
-
The
field
value needs to be identical to thevalue
of this subquery.Applicable to
string
,stringlist
,enum
,multienum
,float
,integer
anddate
fields.Example subquery values:
✔ “Some content.” (exact value)
✘ “Some” (not exact value)
starts_with
The starts_with
is intended for programmatic comparisons of string values.
The starts_with
operator has a precision limit: Only prefixes of up to 20 characters are guaranteed to be matched. If you supply a prefix of more than 20 characters, the additional characters may be ignored.
When combined with the system attribute _path
, the operator starts_with
has some special functionality: There is not precision limit, i.e. a prefix of arbitrary length may be used to match on _path
. Also, prefix matching on _path
automatically matches entire path components, i.e. the prefix matching is delimited by slashes (the character ‘/’).
For starts_with
, the examples are based on the following field value: “Some content.”
:starts_with
-
The
field
value needs to start exactly with thevalue
of this subquery.Applicable to
string
,stringlist
,enum
andmultienum
fields.Example subquery values:
✔ “Som” (prefix of the value)
✘ “som” (incorrect case of prefix)
✘ “content” (not prefix of the whole value)
is_less_than
and is_greater_than
These operators are intended for comparing date
, integer
, or float
values. It only considers attributes of Objs and not of Widgets. Therefore, Widget attributes are not searchable using the is_less_than
and is_greater_than
operators.
For is_less_than
and is_greater_than
, the examples are based on the following date value: Time.new(2000,01,01,00,00,00)
:is_less_than
-
Matches if the field value is less than the subquery string value.
Example subquery values:
✔ Time.new(1999,12,31,23,59,59) (is less than)
✘ Time.new(2000,01,01,00,00,00) (equal, not less than)
:is_greater_than
-
Matches if the field value is greater than the subquery string value.
Example subquery values:
✔ Time.new(2000,01,01,00,00,01) (is greater than)
✘ Time.new(2000,01,01,00,00,00) (equal, not greater than)
For is_less_than
and is_greater_than
, the examples are based on the following float value: 23.42
:is_less_than
-
Matches if the field value is less than the subquery numeric value.
Example subquery values:
✔
23.41
(is less than)✔
5
(is less than)✘
23.42
(equal, not less than) :is_greater_than
-
Matches if the field value is greater than the subquery numeric value.
Example subquery values:
✔
23.43
(is greater than)✔
42
(is greater than)✘
23.42
(equal, not greater than)
links_to
The links_to
operator searches for CMS objects containing one or more attributes linking to specific CMS objects. So the operator returns the CMS objects in which at least one html
, link
, linklist
, reference
or referencelist
attribute links to specific CMS objects.
The operator can only be applied to all attributes, so the “*” wildcard must be specified for the attributes to search. If you want to search specific reference
or referencelist
attributes, please use the refers_to
operator.
Using nil
instead of an instance of Obj raises an error.
Note that, in contrast to the refers_to
operator, the links_to
operator searches the attributes directly part of the CMS objects as well as the attributes contained in widgets.
:links_to
-
Searches for CMS objects linking to a specific CMS object.
Example subquery values:
✔
my_obj
(an instance of Obj)✔ [my_obj1, my_obj2] (an
Array
of instances of Obj)✘
nil
(not an instance of Obj)✘ “some_string” (not an instance of Obj)
refers_to
The refers_to
operator searches for CMS objects in which at least one of the specified reference
or referencelist
attributes refers to specific CMS objects.
Using the “*” wildcard for the attributes to search causes all reference
and referencelist
attributes of the searched CMS objects to be taken into account.
Using nil
instead of Objs searches for all CMS objects in which none of the specified attributes refer to a CMS object.
Note that, in contrast to the links_to
operator, the refers_to
operator only searches attributes directly part of the CMS objects. Currently, attributes contained in widgets are not searched.
:refers_to
-
Searches for CMS objects in which specific
reference
orreferencelist
attributes refer to specific CMS objects.Example subquery values:
✔
my_obj
(an instance of Obj)✔ [my_obj1, my_obj2] (an
Array
of instances of Obj)✔
nil
✘ “some_string” (not an instance of Obj)
Matching multienum
and stringlist
Attributes of type multienum
and stringlist
contain an array of strings. Each of these strings is searched individually. A search query matches a multienum
or stringlist
, if at least one string in the list matches. Example: A query using the operator :equals
and the value “Eggs” matches an Obj containing [“Spam”,“Eggs”] in a stringlist
or multienum
attribute.
Limits
The number of chainable subqueries is limited. The limit depends on the number of values, fields, and boost parameters requested, as well as the number of words in a free text search.
Concurrent changes
Please be aware that concurrent changes can change the search result and can yield incomplete results. This is due to the fact, that search results are lazily loaded in batches. If you want to modify the result of a search, please call to_a
first.
Chainable methods collapse
-
#and(field, operator, value, boost = nil) ⇒ Scrivito::ObjSearchEnumerator
Adds the given AND subquery to this ObjSearchEnumerator.
-
#and_not(field, operator, value) ⇒ Scrivito::ObjSearchEnumerator
Adds the given negated AND subquery to this ObjSearchEnumerator.
-
#batch_size(size) ⇒ Scrivito::ObjSearchEnumerator
Number of search results to be returned by each of the internal search requests.
-
#offset(amount) ⇒ Scrivito::ObjSearchEnumerator
Omits the first
amount
of Objs from the results. -
#order(field_name) ⇒ Scrivito::ObjSearchEnumerator
Orders the results by
field_name
. -
#reverse_order ⇒ Scrivito::ObjSearchEnumerator
deprecated
Deprecated.
This method is deprecated and will be removed in the next major version. Please specify the direction using #order.
Instance Method Summary collapse
-
#each {|Obj| ... }
Iterates over the search result, yielding Obj.
-
#facet(*facet_params) ⇒ Object
Perform a faceted search over up to ten attributes to retrieve structured results for individual values of these attributes.
-
#load_batch ⇒ Array
Loads a single batch of search results from the backend.
-
#size ⇒ Integer
(also: #length, #count)
The total number of hits.
-
#suggest(prefix, options = {}) ⇒ Array<String>
Suggests search terms that start with the provided prefix.
Instance Method Details
#and(field, operator, value, boost = nil) ⇒ Scrivito::ObjSearchEnumerator
Adds the given AND subquery to this Scrivito::ObjSearchEnumerator.
Compares the field(s) with the value(s) using the operator
of this subquery. All CMS objects to which this criterion applies remain in the result set.
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
# File 'app/cms/scrivito/obj_search_enumerator.rb', line 293 def and(field, operator, value, boost = nil) symbolized_operator = ensure_symbol_and_validate_operator(operator) subquery = { field: field, operator: symbolized_operator, value: convert_value(value) } if boost.present? valid_boost_operators = [:contains, :contains_prefix] if valid_boost_operators.include?(symbolized_operator) subquery[:boost] = boost else raise "Boost is not allowed with operator '#{operator}'. " + "Valid operators are: #{valid_boost_operators.join(', ')}" end end reset_for_changed_query @query = (query || []) + [subquery] self end |
#and_not(field, operator, value) ⇒ Scrivito::ObjSearchEnumerator
Adds the given negated AND subquery to this Scrivito::ObjSearchEnumerator.
Compares the field(s) with the value(s) using the negated operator
of this subquery. All CMS objects to which this criterion applies are removed from the result set.
327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'app/cms/scrivito/obj_search_enumerator.rb', line 327 def and_not(field, operator, value) if INVALID_NEGATED_OPERATORS.include?(operator.to_sym) raise "Negating operator '#{operator}' is not valid." end symbolized_operator = ensure_symbol_and_validate_operator(operator) subquery = { field: field, operator: symbolized_operator, value: convert_value(value), negate: true } reset_for_changed_query @query = (query || []) + [subquery] self end |
#batch_size(size) ⇒ Scrivito::ObjSearchEnumerator
Number of search results to be returned by each of the internal search requests.
The default is 10
.
Scrivito makes a best effort to return the given number of search results, but may under certain circumstances return larger or smaller batches due to technical reasons.
405 406 407 408 409 410 |
# File 'app/cms/scrivito/obj_search_enumerator.rb', line 405 def batch_size(size) @batch_size = size @preload_batch = true self end |
#each {|Obj| ... }
This method returns an undefined value.
Iterates over the search result, yielding Obj.
435 436 437 438 439 440 441 442 443 444 445 |
# File 'app/cms/scrivito/obj_search_enumerator.rb', line 435 def each iterator = BatchIterator.new(workspace, search_dsl_params, @preloaded_batch) iterator.each do |batch| batch.objs.each do |obj| yield obj end end @size = iterator.total end |
#facet(attribute, options = {}) ⇒ Array<Scrivito::ObjFacetValue> #facet(facets) ⇒ Hash
Perform a faceted search over up to ten attributes to retrieve structured results for individual values of these attributes.
Applicable to attributes of the following types: string
, stringlist
, enum
, multienum
.
Please note that there is a precision limit for faceting: Only the first 50 characters of a string are guaranteed to be considered for faceting. If two string values have the same first 50 characters, they may be grouped into the same facet value.
Please note that by default #facet does not preload the first batch of the search results. In order to reduce the number of search requests, batch_size
can be explicitly set using the #batch_size method. This causes Scrivito to preload the first batch of the search results.
621 622 623 624 625 626 627 628 629 630 631 |
# File 'app/cms/scrivito/obj_search_enumerator.rb', line 621 def facet(*facet_params) search_params = search_dsl_params search_params[:size] = 0 unless @preload_batch facet_query = FacetQuery.new(facet_params, search_params, workspace) facet_query.execute! @preloaded_batch = facet_query.batch if @preload_batch facet_query.result end |
#load_batch ⇒ Array
Loads a single batch of search results from the backend. Usually returns batch_size
results if available, but may occasionally return more or fewer than batch_size
results (due to technical reasons). If you need an exact number of hits, use methods from Enumerable
, for example take
.
478 479 480 |
# File 'app/cms/scrivito/obj_search_enumerator.rb', line 478 def load_batch fetch_batch.objs end |
#offset(amount) ⇒ Scrivito::ObjSearchEnumerator
Omits the first amount
of Objs from the results. The default is 0
.
417 418 419 420 421 |
# File 'app/cms/scrivito/obj_search_enumerator.rb', line 417 def offset(amount) [:offset] += amount self end |
#order(field_name) ⇒ Scrivito::ObjSearchEnumerator #order(field_and_direction) ⇒ Scrivito::ObjSearchEnumerator
Orders the results by field_name
.
Applicable to the attribute types string
, enum
, integer
, float
and date
.
There is a precision limit when sorting string values: Only the first 50 characters of a string are guaranteed to be considered when sorting search results.
362 363 364 365 366 367 368 369 370 371 372 373 |
# File 'app/cms/scrivito/obj_search_enumerator.rb', line 362 def order(field_name) field_name, direction = if field_name.is_a?(Hash) field_name.to_a.first else [field_name, :asc] end [:sort_by] = field_name [:sort_order] = direction.to_sym self end |
#reverse_order ⇒ Scrivito::ObjSearchEnumerator
380 381 382 383 384 385 386 387 |
# File 'app/cms/scrivito/obj_search_enumerator.rb', line 380 def reverse_order Scrivito::Deprecation.warn_method("reverse_order", "order") [:sort_by].present? or raise "A search order has to be specified"\ " before reverse_order can be applied." [:sort_order] = [:sort_order] == :asc ? :desc : :asc self end |
#size ⇒ Integer Also known as: length, count
The total number of hits.
This number is an approximation. Scrivito makes a best effort to deliver the exact number of hits. But due to technical reasons, the returned number may differ from the actual number under certain circumstances.
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 |
# File 'app/cms/scrivito/obj_search_enumerator.rb', line 455 def size return @size if @size size_query = { query: query, size: 0 } if @include_deleted size_query[:options] = { include_deleted: true } end @size ||= CmsBackend.search_objs(workspace, size_query)['total'].to_i end |
#suggest(prefix, options = {}) ⇒ Array<String>
Suggests search terms that start with the provided prefix.
#suggest
works case insensitive, and all results are converted to lower case.
Preceding calls to #and
or #and_not
may limit the amount of documents that are searched for suggestions.
667 668 669 670 671 672 673 674 675 676 677 |
# File 'app/cms/scrivito/obj_search_enumerator.rb', line 667 def suggest(prefix, = {}) o = .with_indifferent_access params = { prefix: prefix, fields: o[:attributes] || ['*'], limit: o[:limit] || 5, from_search: search_dsl_params, } CmsRestApi.put("workspaces/#{workspace.id}/objs/search/suggest", params)['results'] end |