menu
Oro Inc. OroCommerce
    Contact Us
    close
    • ← Oro Inc. Home
    • OroCommerce
    • Solutions
      Explore solutions according to your need
      By Need
      • Digital TransformationWe’ll help you use technology to build a better business
      • Customer Experience ImprovementStay ahead of buyer expectations across multiple touchpoints
      • Sales AccelerationTrack, analyze, and keep the pulse on your sales activities
      • Operational Efficiency ImprovementMaintain flexibility and innovate with the resources you have
      By Industry
      • Manufacturers
      • Distributors
      • FMCG Industry
      • Medical Supplies
      • Automotive
      • Electronics
      • Industrial Supplies
      • Chemical Industry
      Dunlop Protective Footwear
      Leading global manufacturer of protective footwear opens up new horizons with B2B eCommerce
      • Read the Story
    • Resources
      • Documentation
      • OroAcademy
    • Partners
      • All partners
      • Solution partners
      • Technology partners
      • Consulting Partners
      Want to be a partner?
      At Oro, we are commited to a truly open source ecosystem
      • Become a partner
    • Customers
    • About Us
      About Oro Inc.
      • Company
      • Vision & Mission
      • Leadership Team
      News & Actualities
      • Guides & Reports
      • B2B UnCut Podcast
      • Blog
      • Events
      • Press
      Join our next podcast episode LIVE!
      B2B Commerce UnCut: hear what really matters in B2B
      • Sign Up
    • Contact Us
    Join us on Slack
    • Back to Oro Inc
    • Users
      Concept Guides
      Concept Guides
      • Concept Guides
      • Back-Office
      • Commerce Storefront
      • Glossary
      • Integrations
    • Developers
      • Backend Developer Guide
      • Frontend Developer Guide
      • Bundles & Components
      • Web Services API Guide
      • Community Guide
    • Cloud Administrators
      Cloud Administrators
      Cloud Administrators
      • Architecture
      • Environment Types
      • Security
      • Monitoring
      • Onboarding
      • VPN Connection
      • Maintenance
      • Support
    • Blog
    • Academy
    Join us on Slack
    • Home >
    • Oro Bundles and Components >
    • OroWebsiteSearchBundle >
    • Perform Search
    • Oro Bundles and Components
      • Components
        • Configuration Merger
        • Cumulative Resources
        • System Aware Resolver
        • Resources Loader Factory
      • ActionBundle
      • ActivityBundle
        • Commands
      • ActivityListBundle
      • AddressBundle
      • ApiBundle
      • AssetBundle
        • Commands
      • AttachmentBundle
        • OroAttachmentBundle Configuration
        • Displaying Pictures
        • Generating Image and File URLs
        • Image Placeholder Configuration
      • BatchBundle
      • CacheBundle
      • CalendarBundle
        • Calendar Provider
        • Calendar Context Menu
        • System Calendars
        • Workflow Action
        • Recurring Events
        • UID (Unique Calendar Identifier)
        • Calendar Event Ownership
        • Attendees
      • ChartBundle
      • CommentBundle
      • ConfigBundle
      • CronBundle
      • CurrencyBundle
        • Multi Currency Cell Content Editor
      • DashboardBundle
      • DataAuditBundle
      • DataGridBundle
        • Default Editors
      • DistributionBundle
      • DigitalAssetBundle
      • ElasticSearchBundle
        • Index Agent and Search Engine
        • ElasticSearch Indexes Backup
        • ElasticSearch Configuration
        • Request Builders
        • Troubleshooting
        • Upgrade Website Index to Elasticsearch >=8.4, <9.0
      • EmailBundle
        • Transports
        • Events
        • Emails
        • Email Templates
        • Email Templates Migrations
        • System Mailboxes
        • Email Ownership
        • Sending Emails in Workflows and Actions (Operations)
        • Recipients Autocompletion
        • Public and Private Emails
        • Commands
      • EmbeddedFormBundle
      • EntityBundle
        • EntityModel
        • EntitySelectSearchApiAccessor ⇐ SearchApiAccessor
        • EntityStructureDataProvider
      • EntityConfigBundle
      • EntityExtendBundle
      • EntityMergeBundle
      • EntityPaginationBundle
      • EntitySerializedFieldsBundle
      • FeatureToggleBundle
      • FilterBundle
        • Filter Form Types
        • Grid Extension
      • FormBundle
        • Form Components Overview
        • Update Handler
        • Entity Create or Select Form Type
        • Rich Text Form Type
        • Autocomplete Form Type
        • Text Autocomplete Form Type
        • UI DataBlock Config Overview
        • Expression Editor
        • Client Side Validation
        • InlineEditableViewComponent
        • Index of Supported Editors
          • AbstractRelationEditorView
          • TextEditorView
          • NumberEditorView
          • PercentEditorView
          • DateEditorView
          • DatetimeEditorView
          • SelectEditorView
          • MultiSelectEditorView
          • MultiCheckboxEditorView
          • MultiRelationEditorView
          • RelatedIdRelationEditorView
          • RelatedIdSelectEditorView
        • Search APIs
      • GaufretteBundle
      • GridFSConfigBundle
      • ImapBundle
        • Usage Example
        • Synchronization with IMAP Servers
        • OAuth Providers for Mailboxes
        • User Email Origin Transport
      • ImportExportBundle
        • Commands
      • InstallerBundle
        • Commands
      • IntegrationBundle
      • LayoutBundle
        • Layout Cache
      • LocaleBundle
        • Locale Settings
        • Number Formatting
        • Date and Datetime Formatting
        • Name Formatting
        • Address Formatting
        • Localization
        • Managing Localizations
        • Current Localization
        • Localized Values
        • CLI Commands (LocaleBundle)
      • LoggerBundle
      • MessageQueueBundle
        • Commands
      • MigrationBundle
        • Commands
      • MicrosoftSyncBundle
      • NavigationBundle
        • Menu Updates
        • Commands
      • NoteBundle
      • NotificationBundle
      • OAuth2ServerBundle
      • OrganizationBundle
      • PlatformBundle
        • Commands
      • QueryDesignerBundle
        • Query Designer Configuration
        • Condition Builder Component
      • RedisConfigBundle
        • Configure Redis Servers
        • Configure Application to Use Redis
      • ReportBundle
      • ScopeBundle
      • SearchBundle
        • ORM Search Engine
        • Search Relevance Weight
        • DateTimeFormatter
      • SecurityBundle
      • SegmentBundle
      • SidebarBundle
      • SyncBundle
        • Configuration
        • Client
        • Topics and Handlers
        • Authentication
        • Content Outdating
        • Origin Checking
        • Mediator Handlers
      • TagBundle
        • TagsEditorView
        • TagsView
      • TestFrameworkBundle
        • Additional Doctrine Events
      • ThemeBundle
      • TranslationBundle
        • Commands
      • TwigInspectorBundle
      • UIBundle
        • Action Manager
        • Client Side Navigation
        • Content Providers
        • Dynamic Assets
        • Formatters
        • Scroll Data Customization
        • TWIG Placeholders
        • TWIG Filters
        • Widgets
        • ApiAccessor
        • BaseClass
        • HiddenInitializationView ⇐ BaseView
        • Layout Subtree View
        • LoadMoreCollection
        • Loading Mask View
        • MultiUseResourceManager ⇐ BaseClass
        • PersistentStorage
        • Highlight Text View
        • RouteModel
        • RoutingCollection
        • SearchApiAccessor
        • Viewport Manager
        • Error Handler
        • Input Widgets
        • Items Manager
        • Mediator Handlers
      • WindowsBundle
      • WorkflowBundle
        • Commands
      • DraftBundle
        • How to Use Drafts
        • How to Use Draft ACL
        • How to Use the Draft Filter
        • How to Resolve Draft Conflicts
        • How to Use a Draft Extension
      • CatalogBundle
      • CheckoutBundle
      • CMSBundle
        • Content Widgets
        • WYSIWYG Field
          • How to Add WYSIWYG Field
          • How to Display a WYSIWYG Field
          • How to Change Textarea Field to WYSIWYG Field
          • WYSIWYG Field Validation
        • Content Blocks
        • Create Editor Components
      • ConsentBundle
        • Add the Customer Consents Field to a Form (Example)
        • Add the Agreements Step to a Custom Checkout Based on the Default Checkout Workflow (Example)
        • Add the Agreements Section to a Custom Checkout Based on the Single Page Checkout Workflow (Example)
      • CommerceMenuBundle
        • Main Navigation Menu
        • Menu Updates
        • Menu Templates
        • Content Node Menu Items
        • Category Menu Items
      • CookieConsentBundle
      • CustomerBundle
      • CustomerRecommendationBundle
      • FrontendBundle
        • Frontend Sessions and Debug Routes
        • Frontend Access
        • Set Up Mass Action in Datagrid
        • Sticky Panel View
        • Dom Relocation Global View
      • InventoryBundle
      • OrderBundle
        • Previously Purchased Products
      • PayPalBundle
      • PricingBundle
        • Getting a Product Price
        • Getting Price for a Product Line Item
        • Configure Price List Sharding
        • Optimize Website Indexation and Price Recalculation
        • Combined Price List
        • Price Storage
        • Pricing Strategy
        • Commands
      • PromotionBundle
      • ProductBundle
        • Product Actions
        • Product Attributes
        • Product Kits
        • Product Unit Formatting
        • Product Variant Search
        • Related Items
        • Externally Stored Product Images
        • Product Customization Using Layouts
          • Customize Product View Page
          • Customize Product List Page
          • Customize Product Lists
          • Customize Products SKU Validation
      • RedirectBundle
      • SellerDashboardBundle
      • SEOBundle
        • Sitemap
        • SEO Meta Fields
      • ShoppingListBundle
        • Shopping List in the Storefront
      • TaxBundle
      • WebCatalogBundle
      • WebsiteElasticSearchBundle
        • Website ElasticSearch Search Engine
        • Website ElasticSearch Configuration
        • Attributes Boost
        • Request Builders
        • Upgrade Website Index to Elasticsearch >=8.4, <9.0
        • Search Synonym Management
      • WebsiteSearchBundle
        • Website Search VS Regular Search
        • Website Search Configuration
        • Search Index Structure
        • Console Commands
        • Perform Search
        • Indexation Process
        • Reindexation During Platform Update
        • ORM Search Engine
        • Search Relevance Weight
        • Testing
      • ActivityContactBundle
      • AnalyticsBundle
      • ChannelBundle
      • SalesBundle
      • ApruveBundle
      • AuthorizeNetBundle
      • DotmailerBundle
      • DPDBundle
      • GoogleTagManagerBundle
      • InfinitePayBundle
      • MailchimpBundle
      • MakerBundle
      • PaypalExpressBundle
      • StripeBundle
    • Contents
      • Search Engine
      • Search Query
      • Search Repository

    Perform Search

    Search Engine

    Search engine is an entry point in Oro application that is used to perform search request. Search engine implements Oro\Bundle\SearchBundle\Engine\EngineInterface interface with one method - search(Query $query, array $context = []).

    This method accepts a low level query object (Oro\Bundle\SearchBundle\QueryQuery), sends a request to the search engine and returns result object (Oro\Bundle\SearchBundle\QueryResult). The $context variable may be used to pass additional parameters specific for the search engines. A default website search engine is accessible via the oro_website_search.engine service.

    Search Engine

    Every engine may have its own requests to modify the way request is sent. However, every engine should support the Oro\Bundle\WebsiteSearchBundle\Event\BeforeSearchEvent out of the box. This event is triggered before the engine queries the search index storage, so the developer can check request parameters and modify the query according to the business logics.

    The event name - oro_website_search.before_search - can be used to add a new listener.

    Here is an example of such listener definition:

    services:
        oro_product.product_visibility_restriction_listener:
            class: Oro\Bundle\ProductBundle\EventListener\ProductVisibilityRestrictionListener
            arguments:
                - '@oro_product.product.manager'
                - '@oro_website_search.provider.search_mapping'
            tags:
                - { name: kernel.event_listener, event: oro_website_search.before_search, method: process }
    

    Search Query

    Developer may start constructing a search query by adjusting the Oro\Bundle\SearchBundle\Query\Query example.

    Let’s assume there is a product entity with the following index structure:

    Oro\Bundle\ProductBundle\Entity\Product:
        alias: oro_product
        fields:
            -
                name: sku
                type: text
            -
                name: name
                type: text
            -
                name: price
                type: decimal
    

    and you want the following query to be executed:

    SELECT
        text.sku,
        text.name,
        decimal.price
    FROM
        oro_product
    WHERE
        text.name ~ product
    ORDER_BY
        decimal.price ASC
    

    The following example illustrates how to build and execute such a query:

    use Oro\Bundle\SearchBundle\Query\Query;
    use Oro\Bundle\SearchBundle\Query\Result;
    use Oro\Bundle\SearchBundle\Query\Criteria\Criteria;
    use Oro\Bundle\SearchBundle\Engine\EngineInterface;
    
    $query = new Query();
    $query
        ->addSelect(['text.sku', 'text.name', 'decimal.price'])
        ->from('oro_product');
    $query->getCriteria()
        ->andWhere(Criteria::expr()->contains('text.name', 'product'))
        ->orderBy(['decimal.price' => Query::ORDER_ASC]);
    
    /** @var EngineInterface $engine */
    $engine = $this->getContainer()->get('oro_website_search.engine');
    
    /** @var Result $engine */
    $result = $engine->search($query);
    

    Where the $result variable is an Oro\Bundle\SearchBundle\Query\Result object that contains collection of Oro\Bundle\SearchBundle\Query\Result\Item objects. Every object in the collection contains information about an entity involved in a search query: entity class, entity ID and additional selected data.

    This type of query is used when the search engine and its configuration is unknown, and you need an instance of an engine which implements Oro\Bundle\SearchBundle\Engine\EngineInterface.

    As a universal, search-engine agnostic solution, you may use the Oro\Bundle\WebsiteSearchBundle\Query\WebsiteSearchQuery that implements the Oro\Bundle\SearchBundle\Query\SearchQueryInterface interface. This type does not require additional search-engine-specific parameters and can be used in components that should be able to work with any search engine. Basically, such query encapsulates previous type of query and the required parameters to perform search (in this case it is a search engine).

    To create the latter type of query, you can use specific factory for website search, or use the generic one and specify the index you used:

    $query = $this->container->get('oro_website_search.query_factory')->create();
    // OR
    $query = $this->container->get('oro_search.query_factory')->create(['search_index' => 'website']);
    

    Let’s execute the request to the search index mentioned above using second type of query:

    use Oro\Bundle\SearchBundle\Query\SearchQueryInterface;
    use Oro\Bundle\SearchBundle\Query\Result;
    use Oro\Bundle\SearchBundle\Query\Criteria\Criteria;
    
    /** @var SearchQueryInterface $query */
    $query = $this->container->get('oro_website_search.query_factory')->create();
    $query
        ->addSelect(['text.sku', 'text.name', 'decimal.price'])
        ->setFrom('oro_product')
        ->addWhere(Criteria::expr()->contains('text.name', 'product'))
        ->setOrderBy('decimal.price', Query::ORDER_ASC);
    
    /** @var Result $engine */
    $result = $query->getResult();
    

    As you can see, the interface is similar, but you are not aware about search engine and index type that is used. This information is resolved on the factory level, so you can override and decorate the service that represents the factory to customize search behavior.

    Note

    There is a hard limit of 1000 on quantity of results which search query can return.

    Search Repository

    To store custom queries that are used to receive data from the search index, SearchBundle provides the search repository class – Oro\Bundle\SearchBundle\Query\SearchRepository – with default logic. The WebsiteSearchBundle extends this class and adds Oro\Bundle\WebsiteSearchBundle\Query\WebsiteSearchRepository. The only difference between these repositories is the type of index that is used. Basic repository uses default index from SearchBundle, and the website search repository uses website search index.

    You may want to use website repository to create a specialized repository for an entity in the website search index. Similar to the Doctrine object repository, you can use this one to store the website search related methods.

    Let’s have a look at the example of such repository:

    namespace Oro\Bundle\ProductBundle\Search;
    
    use Oro\Bundle\SearchBundle\Query\Criteria\Criteria;
    use Oro\Bundle\SearchBundle\Query\Query;
    use Oro\Bundle\SearchBundle\Query\Result;
    use Oro\Bundle\SearchBundle\Query\SearchQueryInterface;
    use Oro\Bundle\WebsiteSearchBundle\Query\WebsiteSearchRepository;
    
    class ProductRepository extends WebsiteSearchRepository
    {
        /**
         * @param string $string
         * @return Result
         */
        public function findByAllText($string)
        {
            /** @var SearchQueryInterface $query */
            $query = $this->createQuery();
            $query
                ->addSelect(['text.sku', 'text.name', 'decimal.price'])
                ->addWhere(Criteria::expr()->contains('text.name', $string))
                ->setOrderBy('decimal.price', Query::ORDER_ASC);
    
            return $query->getResult();
        }
    }
    

    This is exactly the same query described before encapsulated in the repository. No need to call the factory methods. Define this repository as a service and use it wherever you need it.

    Below is an example of search repository service declaration:

    services:
        oro_product.website_search.repository.product:
            parent: oro_website_search.repository.abstract
            class: Oro\Bundle\ProductBundle\Search\ProductRepository
            calls:
                - [setEntityName, ['Oro\Bundle\ProductBundle\Entity\Product']]
    

    Parent oro_website_search.repository.abstract service already contains all required constructor arguments. You may specify the entity name to automatically fill the FROM part of the query. This call is optional. If it is missing, an empty query will be created.

    Oro Documentation
    • Oro inc
    • OroCommerce
    • OroMarketplace
    • OroCRM
    • OroPlatform
    • Partners
    • Services
    • Events
    • Twitter
    • Terms & conditions
    • Privacy policy
    • Contributor license agreement

    @2021 Oro, Inc. All Rights Reserved.

    Back to top