workarea 3.4.16 → 3.4.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +81 -0
- metadata +10 -579
- data/docs/Gemfile +0 -8
- data/docs/Gemfile.lock +0 -130
- data/docs/bin/middleman +0 -29
- data/docs/config.rb +0 -87
- data/docs/config.ru +0 -7
- data/docs/data/articles.yml +0 -157
- data/docs/package.json +0 -15
- data/docs/source/404.html.erb +0 -13
- data/docs/source/articles/access-routes-in-javascript.html.md +0 -33
- data/docs/source/articles/add-a-content-area.html.md +0 -169
- data/docs/source/articles/add-a-content-block-type.html.md +0 -334
- data/docs/source/articles/add-a-report.html.md +0 -202
- data/docs/source/articles/add-css-through-the-admin-ui.html.md +0 -30
- data/docs/source/articles/add-javascript-through-a-manifest.html.md +0 -367
- data/docs/source/articles/add-javascript-through-a-view.html.md +0 -80
- data/docs/source/articles/add-javascript-through-the-admin-ui.html.md +0 -30
- data/docs/source/articles/add-metrics.html.md +0 -58
- data/docs/source/articles/add-or-replace-a-pricing-calculator.html.md +0 -150
- data/docs/source/articles/add-remove-or-change-a-mongoid-validation.html.md +0 -147
- data/docs/source/articles/add-remove-or-change-a-product-template.html.md +0 -142
- data/docs/source/articles/add-remove-sort-and-group-storefront-search-filters.html.md +0 -483
- data/docs/source/articles/add-stylesheets-through-a-manifest.html.md +0 -276
- data/docs/source/articles/add-system-content.html.md +0 -138
- data/docs/source/articles/analytics-overview.html.md +0 -51
- data/docs/source/articles/analyze-storefront-search-results.html.md +0 -261
- data/docs/source/articles/api-overview.html.md +0 -35
- data/docs/source/articles/appending.html.md +0 -506
- data/docs/source/articles/application-document.html.md +0 -88
- data/docs/source/articles/automated-javascript-testing.html.md +0 -162
- data/docs/source/articles/b2b-overview.html.md +0 -64
- data/docs/source/articles/browser-and-device-support.html.md +0 -47
- data/docs/source/articles/change-product-placeholder-image.html.md +0 -39
- data/docs/source/articles/change-storefront-search-results.html.md +0 -283
- data/docs/source/articles/change-the-storefront-product-pricing-ui.html.md +0 -348
- data/docs/source/articles/change-the-storefront-search-filters-ui.html.md +0 -103
- data/docs/source/articles/checkout.html.md +0 -479
- data/docs/source/articles/commerce-model.html.md +0 -164
- data/docs/source/articles/configuration-for-hosting.html.md +0 -106
- data/docs/source/articles/configuration.html.md +0 -406
- data/docs/source/articles/configure-a-payment-gateway.html.md +0 -58
- data/docs/source/articles/configure-asset-storage.html.md +0 -29
- data/docs/source/articles/configure-asset-types.html.md +0 -18
- data/docs/source/articles/configure-contact-form-subjects-list.html.md +0 -24
- data/docs/source/articles/configure-imageoptim.html.md +0 -23
- data/docs/source/articles/configure-locales.html.md +0 -45
- data/docs/source/articles/configure-logins-and-authentication.html.md +0 -42
- data/docs/source/articles/configure-low-inventory-threshold.html.md +0 -26
- data/docs/source/articles/configure-product-image-sizes-and-processing.html.md +0 -28
- data/docs/source/articles/content.html.md +0 -554
- data/docs/source/articles/contentable.html.md +0 -41
- data/docs/source/articles/contribute-code.html.md +0 -69
- data/docs/source/articles/contribute-documentation.html.md +0 -60
- data/docs/source/articles/create-a-custom-discount.html.md +0 -234
- data/docs/source/articles/create-a-new-app.html.md +0 -131
- data/docs/source/articles/create-a-plugin.html.md +0 -19
- data/docs/source/articles/create-a-style-guide.html.md +0 -71
- data/docs/source/articles/create-a-theme.html.md +0 -134
- data/docs/source/articles/css-architectural-overview.html.md +0 -89
- data/docs/source/articles/customize-a-helper.html.md +0 -91
- data/docs/source/articles/decoration.html.md +0 -415
- data/docs/source/articles/define-and-configure-inventory-policies.html.md +0 -107
- data/docs/source/articles/documentation-style-guide.html.md +0 -48
- data/docs/source/articles/documentation.html.md +0 -54
- data/docs/source/articles/domain-modeling.html.md +0 -82
- data/docs/source/articles/error-pages.html.md.erb +0 -95
- data/docs/source/articles/extension-overview.html.md +0 -152
- data/docs/source/articles/favicon-support.html.md +0 -112
- data/docs/source/articles/feature-spec-helper-stylesheet.html.md +0 -25
- data/docs/source/articles/featurejs-and-feature-spec-helper.html.md +0 -20
- data/docs/source/articles/help-and-support.html.md +0 -34
- data/docs/source/articles/html-fragment-caching.html.md +0 -46
- data/docs/source/articles/http-caching.html.md +0 -43
- data/docs/source/articles/i18n.html.md +0 -35
- data/docs/source/articles/images-flow.html.md +0 -10
- data/docs/source/articles/index-storefront-search-documents.html.md +0 -104
- data/docs/source/articles/infrastructure.html.md +0 -46
- data/docs/source/articles/installing.html.md +0 -61
- data/docs/source/articles/integrate-a-payment-gateway.html.md +0 -124
- data/docs/source/articles/integrate-a-web-analytics-provider.html.md +0 -35
- data/docs/source/articles/integrate-an-inventory-management-system.html.md +0 -88
- data/docs/source/articles/integrating-with-other-software.html.md +0 -59
- data/docs/source/articles/inventory.html.md +0 -352
- data/docs/source/articles/javascript-coding-standards.html.md +0 -30
- data/docs/source/articles/javascript-modules.html.md +0 -174
- data/docs/source/articles/javascript-overview.html.md +0 -62
- data/docs/source/articles/javascript-reference-documentation.html.md +0 -51
- data/docs/source/articles/javascript-templates.html.md +0 -52
- data/docs/source/articles/low-level-caching.html.md +0 -25
- data/docs/source/articles/maintain-a-plugin.html.md +0 -12
- data/docs/source/articles/maintenance-policy.html.md +0 -79
- data/docs/source/articles/navigable.html.md +0 -51
- data/docs/source/articles/navigating-the-code.html.md +0 -149
- data/docs/source/articles/navigation.html.md +0 -386
- data/docs/source/articles/order-life-cycle.html.md +0 -546
- data/docs/source/articles/order-pricing.html.md +0 -389
- data/docs/source/articles/orders-and-items.html.md +0 -210
- data/docs/source/articles/orders.html.md +0 -66
- data/docs/source/articles/overriding.html.md +0 -155
- data/docs/source/articles/overview.html.md +0 -43
- data/docs/source/articles/plugins-overview.html.md +0 -12
- data/docs/source/articles/prerequisites-and-dependencies.html.md +0 -202
- data/docs/source/articles/products.html.md.erb +0 -1270
- data/docs/source/articles/progressive-web-application-support.html.md +0 -148
- data/docs/source/articles/rails-asset-manifests.html.md +0 -33
- data/docs/source/articles/rails-asset-view-helpers.html.md +0 -25
- data/docs/source/articles/reading-data.html.md +0 -10
- data/docs/source/articles/releasable.html.md +0 -37
- data/docs/source/articles/report-a-bug.html.md +0 -75
- data/docs/source/articles/ruby-coding-standards.html.md +0 -10
- data/docs/source/articles/run-sidekiq-in-a-local-environment.html.md +0 -40
- data/docs/source/articles/searching.html.md +0 -1005
- data/docs/source/articles/security-policy.html.md +0 -42
- data/docs/source/articles/seeds.html.md +0 -345
- data/docs/source/articles/shipping.html.md +0 -756
- data/docs/source/articles/sort-and-exclude-product-options.html.md +0 -47
- data/docs/source/articles/storefront-search-features.html.md +0 -568
- data/docs/source/articles/storefront-searches.html.md +0 -126
- data/docs/source/articles/style-guides.html.md +0 -21
- data/docs/source/articles/stylesheet-coding-standards.html.md +0 -24
- data/docs/source/articles/stylesheets-overview.html.md +0 -67
- data/docs/source/articles/swappable-list-data-structure.html.md +0 -81
- data/docs/source/articles/system-emails.html.md +0 -102
- data/docs/source/articles/taggable.html.md +0 -8
- data/docs/source/articles/test-a-credit-card-transaction.html.md +0 -16
- data/docs/source/articles/test-if-a-plugin-is-installed.html.md +0 -34
- data/docs/source/articles/testing.html.md +0 -914
- data/docs/source/articles/themes-overview.html.md +0 -155
- data/docs/source/articles/translate-administrable-content.html.md +0 -14
- data/docs/source/articles/translate-javascript-content.html.md +0 -16
- data/docs/source/articles/translate-or-customize-message-content.html.md +0 -29
- data/docs/source/articles/translate-or-customize-static-content.html.md +0 -30
- data/docs/source/articles/use-an-existing-workarea-app.html.md +0 -108
- data/docs/source/articles/view-models.html.md +0 -509
- data/docs/source/articles/views.html.md +0 -14
- data/docs/source/articles/workers.html.md +0 -613
- data/docs/source/articles/writing-data.html.md +0 -10
- data/docs/source/cli.html.md +0 -163
- data/docs/source/favicon.ico +0 -0
- data/docs/source/images/3-variants-1-option.png +0 -0
- data/docs/source/images/3-variants-3-options.png +0 -0
- data/docs/source/images/3-years-primary-image.png +0 -0
- data/docs/source/images/404-storefront-error-page.png +0 -0
- data/docs/source/images/404-system-content-admin.png +0 -0
- data/docs/source/images/404.jpg +0 -0
- data/docs/source/images/5-years-primary-image.png +0 -0
- data/docs/source/images/activity-dashboard.png +0 -0
- data/docs/source/images/activity-for-object.png +0 -0
- data/docs/source/images/activity-ui.png +0 -0
- data/docs/source/images/adding-captioned-image-block-custom-icon.png +0 -0
- data/docs/source/images/adding-captioned-image-block-default-icon.png +0 -0
- data/docs/source/images/admin-alerts-ui.png +0 -0
- data/docs/source/images/admin-category-range-filters.png +0 -0
- data/docs/source/images/admin-for-3-column-hero.png +0 -0
- data/docs/source/images/admin-help-index.png +0 -0
- data/docs/source/images/admin-help-ui.png +0 -0
- data/docs/source/images/admin-javascript.png +0 -0
- data/docs/source/images/admin-notification-for-deactivated-discount.png +0 -0
- data/docs/source/images/admin-notifications-ui.png +0 -0
- data/docs/source/images/admin-product-show-page.png +0 -0
- data/docs/source/images/admin-products-index-page.png +0 -0
- data/docs/source/images/admin-range-filters.png +0 -0
- data/docs/source/images/admin-style-guides-navigation.png +0 -0
- data/docs/source/images/after-re-seeding.png +0 -0
- data/docs/source/images/after-seeding-localhost-3000.png +0 -0
- data/docs/source/images/after-seeding.png +0 -0
- data/docs/source/images/arrow.svg +0 -1
- data/docs/source/images/arrow_white.svg +0 -1
- data/docs/source/images/aws-resource-map.png +0 -0
- data/docs/source/images/backordered-until-output-on-inventory-sku-card.png +0 -0
- data/docs/source/images/before-seeding-localhost-3000.png +0 -0
- data/docs/source/images/before-seeding.png +0 -0
- data/docs/source/images/browsing-workarea-versions-on-the-web.png +0 -0
- data/docs/source/images/bulk-asset-upload-on-assets-index-page.png +0 -0
- data/docs/source/images/bulk-asset-upload-while-editing-content.png +0 -0
- data/docs/source/images/bundle-show-workarea-core.png +0 -0
- data/docs/source/images/bundle-show-workarea.png +0 -0
- data/docs/source/images/calendar-for-backordered-until-field.png +0 -0
- data/docs/source/images/captioned-image-block-in-storefront.png +0 -0
- data/docs/source/images/captioned-image-content-block-storefront-component-style-guide.png +0 -0
- data/docs/source/images/cart-system-content-in-admin.png +0 -0
- data/docs/source/images/cart-system-content-in-storefront.png +0 -0
- data/docs/source/images/checkout-addresses-guest.png +0 -0
- data/docs/source/images/checkout-addresses-user.png +0 -0
- data/docs/source/images/checkout-confirmation.png +0 -0
- data/docs/source/images/checkout-flow-0.png +0 -0
- data/docs/source/images/checkout-flow-1.png +0 -0
- data/docs/source/images/checkout-flow-2.png +0 -0
- data/docs/source/images/checkout-flow-3.png +0 -0
- data/docs/source/images/checkout-flow-4.png +0 -0
- data/docs/source/images/checkout-payment-guest.png +0 -0
- data/docs/source/images/checkout-payment-user.png +0 -0
- data/docs/source/images/checkout-shipping.png +0 -0
- data/docs/source/images/color-picker-component-admin-style-guide.png +0 -0
- data/docs/source/images/color-picker-component-on-content-editing-screen.png +0 -0
- data/docs/source/images/commerce-model-carts-orders.png +0 -0
- data/docs/source/images/commerce-model-order-pricing.png +0 -0
- data/docs/source/images/commerce-model.png +0 -0
- data/docs/source/images/configuring-an-index-pattern-in-kibana.png +0 -0
- data/docs/source/images/content-block-presets.png +0 -0
- data/docs/source/images/content-search-customization.png +0 -0
- data/docs/source/images/country-with-region-data-in-address-form.png +0 -0
- data/docs/source/images/country-without-region-data-in-address-form.png +0 -0
- data/docs/source/images/create-content-block-preset-ui.png +0 -0
- data/docs/source/images/credit-card-icons.png +0 -0
- data/docs/source/images/css-added-through-admin.png +0 -0
- data/docs/source/images/css-admin-ui.png +0 -0
- data/docs/source/images/current-configuration-shown-in-admin-settings.png +0 -0
- data/docs/source/images/customer-impersonation-in-admin.png +0 -0
- data/docs/source/images/customer-impersonation-in-store-front.png +0 -0
- data/docs/source/images/date-filter-same-day.png +0 -0
- data/docs/source/images/developer-toolbar-in-store-front.png +0 -0
- data/docs/source/images/discounts-sorted-by-most-redeemed.png +0 -0
- data/docs/source/images/edit-help-article.png +0 -0
- data/docs/source/images/editing-content-for-search-customization.png +0 -0
- data/docs/source/images/editing-dynamic-captioned-image-block.png +0 -0
- data/docs/source/images/editing-product-fields-in-the-admin.png +0 -0
- data/docs/source/images/editing-search-system-content.png +0 -0
- data/docs/source/images/editing-static-captioned-image-block-custom-icon.png +0 -0
- data/docs/source/images/editing-static-captioned-image-block-default-icon.png +0 -0
- data/docs/source/images/external.svg +0 -1
- data/docs/source/images/favicon_16.png +0 -0
- data/docs/source/images/favicon_180.png +0 -0
- data/docs/source/images/favicon_32.png +0 -0
- data/docs/source/images/filters-all.png +0 -0
- data/docs/source/images/filters-control.png +0 -0
- data/docs/source/images/filters-custom.png +0 -0
- data/docs/source/images/filters-groups.png +0 -0
- data/docs/source/images/filters-material.png +0 -0
- data/docs/source/images/filters-omitted.png +0 -0
- data/docs/source/images/filters-pinned.png +0 -0
- data/docs/source/images/filters-range.png +0 -0
- data/docs/source/images/filters-sorted.png +0 -0
- data/docs/source/images/filters-wrapping-to-second-line-in-admin.png +0 -0
- data/docs/source/images/generic-product-template-images-no-options-selected.png +0 -0
- data/docs/source/images/generic-product-template-images-options-selected.png +0 -0
- data/docs/source/images/generic-template.png +0 -0
- data/docs/source/images/hosting.svg +0 -1
- data/docs/source/images/image-group-content-block-in-storefront.png +0 -0
- data/docs/source/images/images.svg +0 -1
- data/docs/source/images/import-export-screenshot.png +0 -0
- data/docs/source/images/invalid-display.png +0 -0
- data/docs/source/images/itcss.png +0 -0
- data/docs/source/images/kibana-dev-tools-console.png +0 -0
- data/docs/source/images/layout-content-admin-with-2-areas.png +0 -0
- data/docs/source/images/layout-content-admin-with-3-areas.png +0 -0
- data/docs/source/images/link-to-search-system-content.png +0 -0
- data/docs/source/images/logo.svg +0 -1
- data/docs/source/images/menu.svg +0 -2
- data/docs/source/images/mongo-replica-set.svg +0 -1
- data/docs/source/images/multi-column-hero-blocks.png +0 -0
- data/docs/source/images/option-selects-product-template-images-options-selected.png +0 -0
- data/docs/source/images/option-selects-template.png +0 -0
- data/docs/source/images/option-thumbnails-template.png +0 -0
- data/docs/source/images/order-item-total-price-diagram.png +0 -0
- data/docs/source/images/order-pricing-cart-example.png +0 -0
- data/docs/source/images/order-pricing-example-adjustments.png +0 -0
- data/docs/source/images/order-pricing-example-totals.png +0 -0
- data/docs/source/images/order-pricing-placed-order-example.png +0 -0
- data/docs/source/images/order-shipping-total-diagram.png +0 -0
- data/docs/source/images/order-show-with-multiple-tenders.png +0 -0
- data/docs/source/images/order-subtotal-price-diagram.png +0 -0
- data/docs/source/images/order-tax-total-diagram.png +0 -0
- data/docs/source/images/order-total-price-diagram.png +0 -0
- data/docs/source/images/order-total-value-diagram.png +0 -0
- data/docs/source/images/orders-dashboard-links.png +0 -0
- data/docs/source/images/oval.svg +0 -1
- data/docs/source/images/payment-icon-storefront-style-guide.png +0 -0
- data/docs/source/images/people-dashboard-links.png +0 -0
- data/docs/source/images/price-adjustments-diagram.png +0 -0
- data/docs/source/images/price-display-no-options.png +0 -0
- data/docs/source/images/price-display-options-selected.png +0 -0
- data/docs/source/images/pricing-calculators-diagram.png +0 -0
- data/docs/source/images/product-list-content-block-admin.png +0 -0
- data/docs/source/images/product-list-content-block-in-store-front.png +0 -0
- data/docs/source/images/promo-products-excluded-autocomplete-results-after.png +0 -0
- data/docs/source/images/promo-products-excluded-featured-category-results-after.png +0 -0
- data/docs/source/images/promo-products-excluded-recommendations-results-after.png +0 -0
- data/docs/source/images/promo-products-excluded-search-category-results-after.png +0 -0
- data/docs/source/images/promo-products-excluded-search-results-after.png +0 -0
- data/docs/source/images/promo-products-included-autocomplete-results-before.png +0 -0
- data/docs/source/images/promo-products-included-featured-category-results-before.png +0 -0
- data/docs/source/images/promo-products-included-recommendations-results-before.png +0 -0
- data/docs/source/images/promo-products-included-search-category-results-before.png +0 -0
- data/docs/source/images/promo-products-included-search-results-before.png +0 -0
- data/docs/source/images/rails-version-constraint.png +0 -0
- data/docs/source/images/re-enable-discount.png +0 -0
- data/docs/source/images/reading-data.svg +0 -1
- data/docs/source/images/readme-hero.png +0 -0
- data/docs/source/images/redesigned-customized-sort-for-search-results.png +0 -0
- data/docs/source/images/reviews-summary-above-share-buttons.png +0 -0
- data/docs/source/images/reviews-summary-below-product-name.png +0 -0
- data/docs/source/images/reviews-summary-below-share-buttons.png +0 -0
- data/docs/source/images/reviews-summary-removed.png +0 -0
- data/docs/source/images/rsa-fingerprint-for-stash.png +0 -0
- data/docs/source/images/ruby-version-constraint.png +0 -0
- data/docs/source/images/script-tag-added-through-admin.png +0 -0
- data/docs/source/images/search-analysis-admin-alternate-rendering.png +0 -0
- data/docs/source/images/search-analysis-admin.png +0 -0
- data/docs/source/images/search-quality-report.png +0 -0
- data/docs/source/images/search.svg +0 -1
- data/docs/source/images/searching-for-cart-system-content-in-admin.png +0 -0
- data/docs/source/images/searching-for-layout-system-content-in-admin.png +0 -0
- data/docs/source/images/seeded-admin.png +0 -0
- data/docs/source/images/seeds-from-plugins.png +0 -0
- data/docs/source/images/seo-metadata-automation-ui.png +0 -0
- data/docs/source/images/show-password-button.png +0 -0
- data/docs/source/images/storefront-autocomplete.png +0 -0
- data/docs/source/images/storefront-category-summary-content-block.png +0 -0
- data/docs/source/images/storefront-category.png +0 -0
- data/docs/source/images/storefront-product-after-overriding.png +0 -0
- data/docs/source/images/storefront-product-before-overriding.png +0 -0
- data/docs/source/images/storefront-product-browse-page.png +0 -0
- data/docs/source/images/storefront-product-recommendations.png +0 -0
- data/docs/source/images/storefront-product-show-page.png +0 -0
- data/docs/source/images/storefront-requests-and-search-requests.png +0 -0
- data/docs/source/images/storefront-search-request-handling.png +0 -0
- data/docs/source/images/storefront-search-response-creation.png +0 -0
- data/docs/source/images/storefront-search.png +0 -0
- data/docs/source/images/storefront-style-guides-navigation.png +0 -0
- data/docs/source/images/styles.css +0 -3
- data/docs/source/images/tax-categories-ui.png +0 -0
- data/docs/source/images/tax-rates-ui.png +0 -0
- data/docs/source/images/unpurchasable-product.png +0 -0
- data/docs/source/images/url-redirects-filtering.png +0 -0
- data/docs/source/images/utility-nav-area-in-admin.png +0 -0
- data/docs/source/images/utility-nav-area-in-storefront.png +0 -0
- data/docs/source/images/validation-message-in-storefront.png +0 -0
- data/docs/source/images/view-model-interface.png +0 -0
- data/docs/source/images/viewing-workarea-version-in-source.png +0 -0
- data/docs/source/images/workarea.svg +0 -1
- data/docs/source/images/worst-performing-searches-on-results-customization-page.png +0 -0
- data/docs/source/images/writing-data.svg +0 -1
- data/docs/source/index.html.erb +0 -166
- data/docs/source/javascripts/jquery.js +0 -2
- data/docs/source/javascripts/lunr.js +0 -7
- data/docs/source/javascripts/site.js +0 -299
- data/docs/source/javascripts/vendor/highlight.pack.js +0 -2
- data/docs/source/layouts/article.erb +0 -106
- data/docs/source/layouts/bare.erb +0 -46
- data/docs/source/layouts/layout.erb +0 -43
- data/docs/source/release-notes/workarea-3-0-0.html.md +0 -146
- data/docs/source/release-notes/workarea-3-0-1.html.md +0 -161
- data/docs/source/release-notes/workarea-3-0-10.html.md +0 -39
- data/docs/source/release-notes/workarea-3-0-11.html.md +0 -277
- data/docs/source/release-notes/workarea-3-0-12.html.md +0 -14
- data/docs/source/release-notes/workarea-3-0-13.html.md +0 -153
- data/docs/source/release-notes/workarea-3-0-14.html.md +0 -93
- data/docs/source/release-notes/workarea-3-0-15.html.md +0 -107
- data/docs/source/release-notes/workarea-3-0-16.html.md +0 -36
- data/docs/source/release-notes/workarea-3-0-17.html.md +0 -141
- data/docs/source/release-notes/workarea-3-0-18.html.md +0 -123
- data/docs/source/release-notes/workarea-3-0-19.html.md +0 -160
- data/docs/source/release-notes/workarea-3-0-2.html.md +0 -222
- data/docs/source/release-notes/workarea-3-0-20.html.md +0 -95
- data/docs/source/release-notes/workarea-3-0-21.html.md +0 -168
- data/docs/source/release-notes/workarea-3-0-22.html.md +0 -268
- data/docs/source/release-notes/workarea-3-0-23.html.md +0 -173
- data/docs/source/release-notes/workarea-3-0-24.html.md +0 -19
- data/docs/source/release-notes/workarea-3-0-25.html.md +0 -26
- data/docs/source/release-notes/workarea-3-0-26.html.md +0 -199
- data/docs/source/release-notes/workarea-3-0-27.html.md +0 -113
- data/docs/source/release-notes/workarea-3-0-28.html.md +0 -39
- data/docs/source/release-notes/workarea-3-0-29.html.md +0 -73
- data/docs/source/release-notes/workarea-3-0-3.html.md +0 -35
- data/docs/source/release-notes/workarea-3-0-30.html.md +0 -186
- data/docs/source/release-notes/workarea-3-0-31.html.md +0 -125
- data/docs/source/release-notes/workarea-3-0-32.html.md +0 -73
- data/docs/source/release-notes/workarea-3-0-33.html.md +0 -137
- data/docs/source/release-notes/workarea-3-0-34.html.md +0 -203
- data/docs/source/release-notes/workarea-3-0-35.html.md +0 -205
- data/docs/source/release-notes/workarea-3-0-36.html.md +0 -105
- data/docs/source/release-notes/workarea-3-0-37.html.md +0 -144
- data/docs/source/release-notes/workarea-3-0-38.html.md +0 -73
- data/docs/source/release-notes/workarea-3-0-39.html.md +0 -77
- data/docs/source/release-notes/workarea-3-0-4.html.md +0 -14
- data/docs/source/release-notes/workarea-3-0-40.html.md +0 -130
- data/docs/source/release-notes/workarea-3-0-41.html.md +0 -70
- data/docs/source/release-notes/workarea-3-0-42.html.md +0 -52
- data/docs/source/release-notes/workarea-3-0-43.html.md +0 -72
- data/docs/source/release-notes/workarea-3-0-44.html.md +0 -93
- data/docs/source/release-notes/workarea-3-0-45.html.md +0 -61
- data/docs/source/release-notes/workarea-3-0-46.html.md +0 -171
- data/docs/source/release-notes/workarea-3-0-47.html.md +0 -130
- data/docs/source/release-notes/workarea-3-0-48.html.md +0 -160
- data/docs/source/release-notes/workarea-3-0-49.html.md +0 -28
- data/docs/source/release-notes/workarea-3-0-5.html.md +0 -225
- data/docs/source/release-notes/workarea-3-0-50.html.md +0 -74
- data/docs/source/release-notes/workarea-3-0-51.html.md +0 -61
- data/docs/source/release-notes/workarea-3-0-52.html.md +0 -76
- data/docs/source/release-notes/workarea-3-0-53.html.md +0 -126
- data/docs/source/release-notes/workarea-3-0-54.html.md +0 -112
- data/docs/source/release-notes/workarea-3-0-55.html.md +0 -105
- data/docs/source/release-notes/workarea-3-0-56.html.md +0 -56
- data/docs/source/release-notes/workarea-3-0-57.html.md +0 -82
- data/docs/source/release-notes/workarea-3-0-58.html.md +0 -153
- data/docs/source/release-notes/workarea-3-0-59.html.md +0 -78
- data/docs/source/release-notes/workarea-3-0-6.html.md +0 -165
- data/docs/source/release-notes/workarea-3-0-60.html.md +0 -43
- data/docs/source/release-notes/workarea-3-0-61.html.md +0 -46
- data/docs/source/release-notes/workarea-3-0-62.html.md +0 -23
- data/docs/source/release-notes/workarea-3-0-63.html.md +0 -25
- data/docs/source/release-notes/workarea-3-0-64.html.md +0 -25
- data/docs/source/release-notes/workarea-3-0-65.html.md +0 -37
- data/docs/source/release-notes/workarea-3-0-7.html.md +0 -207
- data/docs/source/release-notes/workarea-3-0-8.html.md +0 -337
- data/docs/source/release-notes/workarea-3-0-9.html.md +0 -196
- data/docs/source/release-notes/workarea-3-1-0.html.md +0 -414
- data/docs/source/release-notes/workarea-3-1-1.html.md +0 -139
- data/docs/source/release-notes/workarea-3-1-10.html.md +0 -19
- data/docs/source/release-notes/workarea-3-1-11.html.md +0 -27
- data/docs/source/release-notes/workarea-3-1-12.html.md +0 -216
- data/docs/source/release-notes/workarea-3-1-13.html.md +0 -113
- data/docs/source/release-notes/workarea-3-1-14.html.md +0 -39
- data/docs/source/release-notes/workarea-3-1-15.html.md +0 -107
- data/docs/source/release-notes/workarea-3-1-16.html.md +0 -188
- data/docs/source/release-notes/workarea-3-1-17.html.md +0 -141
- data/docs/source/release-notes/workarea-3-1-18.html.md +0 -73
- data/docs/source/release-notes/workarea-3-1-19.html.md +0 -137
- data/docs/source/release-notes/workarea-3-1-2.html.md +0 -55
- data/docs/source/release-notes/workarea-3-1-20.html.md +0 -203
- data/docs/source/release-notes/workarea-3-1-21.html.md +0 -205
- data/docs/source/release-notes/workarea-3-1-22.html.md +0 -121
- data/docs/source/release-notes/workarea-3-1-23.html.md +0 -144
- data/docs/source/release-notes/workarea-3-1-24.html.md +0 -94
- data/docs/source/release-notes/workarea-3-1-25.html.md +0 -77
- data/docs/source/release-notes/workarea-3-1-26.html.md +0 -130
- data/docs/source/release-notes/workarea-3-1-27.html.md +0 -70
- data/docs/source/release-notes/workarea-3-1-28.html.md +0 -52
- data/docs/source/release-notes/workarea-3-1-29.html.md +0 -44
- data/docs/source/release-notes/workarea-3-1-3.html.md +0 -185
- data/docs/source/release-notes/workarea-3-1-30.html.md +0 -72
- data/docs/source/release-notes/workarea-3-1-31.html.md +0 -93
- data/docs/source/release-notes/workarea-3-1-32.html.md +0 -61
- data/docs/source/release-notes/workarea-3-1-33.html.md +0 -171
- data/docs/source/release-notes/workarea-3-1-34.html.md +0 -130
- data/docs/source/release-notes/workarea-3-1-35.html.md +0 -179
- data/docs/source/release-notes/workarea-3-1-36.html.md +0 -28
- data/docs/source/release-notes/workarea-3-1-37.html.md +0 -74
- data/docs/source/release-notes/workarea-3-1-38.html.md +0 -61
- data/docs/source/release-notes/workarea-3-1-39.html.md +0 -96
- data/docs/source/release-notes/workarea-3-1-4.html.md +0 -148
- data/docs/source/release-notes/workarea-3-1-40.html.md +0 -126
- data/docs/source/release-notes/workarea-3-1-41.html.md +0 -128
- data/docs/source/release-notes/workarea-3-1-42.html.md +0 -105
- data/docs/source/release-notes/workarea-3-1-43.html.md +0 -37
- data/docs/source/release-notes/workarea-3-1-44.html.md +0 -82
- data/docs/source/release-notes/workarea-3-1-45.html.md +0 -153
- data/docs/source/release-notes/workarea-3-1-46.html.md +0 -91
- data/docs/source/release-notes/workarea-3-1-47.html.md +0 -65
- data/docs/source/release-notes/workarea-3-1-48.html.md +0 -46
- data/docs/source/release-notes/workarea-3-1-49.html.md +0 -23
- data/docs/source/release-notes/workarea-3-1-5.html.md +0 -169
- data/docs/source/release-notes/workarea-3-1-50.html.md +0 -42
- data/docs/source/release-notes/workarea-3-1-51.html.md +0 -25
- data/docs/source/release-notes/workarea-3-1-52.html.md +0 -57
- data/docs/source/release-notes/workarea-3-1-6.html.md +0 -117
- data/docs/source/release-notes/workarea-3-1-7.html.md +0 -176
- data/docs/source/release-notes/workarea-3-1-8.html.md +0 -283
- data/docs/source/release-notes/workarea-3-1-9.html.md +0 -212
- data/docs/source/release-notes/workarea-3-2-0.html.md +0 -1705
- data/docs/source/release-notes/workarea-3-2-1.html.md +0 -216
- data/docs/source/release-notes/workarea-3-2-10.html.md +0 -237
- data/docs/source/release-notes/workarea-3-2-11.html.md +0 -121
- data/docs/source/release-notes/workarea-3-2-12.html.md +0 -145
- data/docs/source/release-notes/workarea-3-2-13.html.md +0 -138
- data/docs/source/release-notes/workarea-3-2-14.html.md +0 -77
- data/docs/source/release-notes/workarea-3-2-15.html.md +0 -130
- data/docs/source/release-notes/workarea-3-2-16.html.md +0 -111
- data/docs/source/release-notes/workarea-3-2-17.html.md +0 -52
- data/docs/source/release-notes/workarea-3-2-18.html.md +0 -44
- data/docs/source/release-notes/workarea-3-2-19.html.md +0 -72
- data/docs/source/release-notes/workarea-3-2-2.html.md +0 -145
- data/docs/source/release-notes/workarea-3-2-20.html.md +0 -93
- data/docs/source/release-notes/workarea-3-2-21.html.md +0 -61
- data/docs/source/release-notes/workarea-3-2-22.html.md +0 -154
- data/docs/source/release-notes/workarea-3-2-23.html.md +0 -130
- data/docs/source/release-notes/workarea-3-2-24.html.md +0 -200
- data/docs/source/release-notes/workarea-3-2-25.html.md +0 -28
- data/docs/source/release-notes/workarea-3-2-26.html.md +0 -94
- data/docs/source/release-notes/workarea-3-2-27.html.md +0 -61
- data/docs/source/release-notes/workarea-3-2-28.html.md +0 -96
- data/docs/source/release-notes/workarea-3-2-29.html.md +0 -126
- data/docs/source/release-notes/workarea-3-2-30.html.md +0 -112
- data/docs/source/release-notes/workarea-3-2-31.html.md +0 -105
- data/docs/source/release-notes/workarea-3-2-32.html.md +0 -56
- data/docs/source/release-notes/workarea-3-2-33.html.md +0 -82
- data/docs/source/release-notes/workarea-3-2-34.html.md +0 -153
- data/docs/source/release-notes/workarea-3-2-35.html.md +0 -91
- data/docs/source/release-notes/workarea-3-2-36.html.md +0 -118
- data/docs/source/release-notes/workarea-3-2-37.html.md +0 -46
- data/docs/source/release-notes/workarea-3-2-38.html.md +0 -23
- data/docs/source/release-notes/workarea-3-2-39.html.md +0 -42
- data/docs/source/release-notes/workarea-3-2-4.html.md +0 -109
- data/docs/source/release-notes/workarea-3-2-40.html.md +0 -25
- data/docs/source/release-notes/workarea-3-2-41.html.md +0 -90
- data/docs/source/release-notes/workarea-3-2-5.html.md +0 -186
- data/docs/source/release-notes/workarea-3-2-6.html.md +0 -173
- data/docs/source/release-notes/workarea-3-2-7.html.md +0 -89
- data/docs/source/release-notes/workarea-3-2-8.html.md +0 -137
- data/docs/source/release-notes/workarea-3-2-9.html.md +0 -219
- data/docs/source/release-notes/workarea-3-3-0.html.md +0 -1272
- data/docs/source/release-notes/workarea-3-3-1.html.md +0 -324
- data/docs/source/release-notes/workarea-3-3-10.html.md +0 -69
- data/docs/source/release-notes/workarea-3-3-11.html.md +0 -72
- data/docs/source/release-notes/workarea-3-3-12.html.md +0 -136
- data/docs/source/release-notes/workarea-3-3-13.html.md +0 -61
- data/docs/source/release-notes/workarea-3-3-14.html.md +0 -196
- data/docs/source/release-notes/workarea-3-3-15.html.md +0 -167
- data/docs/source/release-notes/workarea-3-3-16.html.md +0 -234
- data/docs/source/release-notes/workarea-3-3-17.html.md +0 -82
- data/docs/source/release-notes/workarea-3-3-18.html.md +0 -165
- data/docs/source/release-notes/workarea-3-3-19.html.md +0 -106
- data/docs/source/release-notes/workarea-3-3-2.html.md +0 -72
- data/docs/source/release-notes/workarea-3-3-20.html.md +0 -116
- data/docs/source/release-notes/workarea-3-3-21.html.md +0 -228
- data/docs/source/release-notes/workarea-3-3-22.html.md +0 -125
- data/docs/source/release-notes/workarea-3-3-23.html.md +0 -154
- data/docs/source/release-notes/workarea-3-3-24.html.md +0 -70
- data/docs/source/release-notes/workarea-3-3-25.html.md +0 -114
- data/docs/source/release-notes/workarea-3-3-26.html.md +0 -260
- data/docs/source/release-notes/workarea-3-3-27.html.md +0 -138
- data/docs/source/release-notes/workarea-3-3-28.html.md +0 -147
- data/docs/source/release-notes/workarea-3-3-29.html.md +0 -63
- data/docs/source/release-notes/workarea-3-3-3.html.md +0 -153
- data/docs/source/release-notes/workarea-3-3-30.html.md +0 -102
- data/docs/source/release-notes/workarea-3-3-31.html.md +0 -57
- data/docs/source/release-notes/workarea-3-3-32.html.md +0 -44
- data/docs/source/release-notes/workarea-3-3-33.html.md +0 -114
- data/docs/source/release-notes/workarea-3-3-34.html.md +0 -29
- data/docs/source/release-notes/workarea-3-3-4.html.md +0 -332
- data/docs/source/release-notes/workarea-3-3-5.html.md +0 -242
- data/docs/source/release-notes/workarea-3-3-6.html.md +0 -100
- data/docs/source/release-notes/workarea-3-3-7.html.md +0 -148
- data/docs/source/release-notes/workarea-3-3-8.html.md +0 -163
- data/docs/source/release-notes/workarea-3-3-9.html.md +0 -93
- data/docs/source/release-notes/workarea-3-4-0.html.md +0 -580
- data/docs/source/release-notes/workarea-3-4-1.html.md +0 -150
- data/docs/source/release-notes/workarea-3-4-10.html.md +0 -72
- data/docs/source/release-notes/workarea-3-4-11.html.md +0 -60
- data/docs/source/release-notes/workarea-3-4-12.html.md +0 -155
- data/docs/source/release-notes/workarea-3-4-15.html.md +0 -100
- data/docs/source/release-notes/workarea-3-4-16.html.md +0 -88
- data/docs/source/release-notes/workarea-3-4-2.html.md +0 -188
- data/docs/source/release-notes/workarea-3-4-3.html.md +0 -136
- data/docs/source/release-notes/workarea-3-4-4.html.md +0 -114
- data/docs/source/release-notes/workarea-3-4-5.html.md +0 -275
- data/docs/source/release-notes/workarea-3-4-6.html.md +0 -169
- data/docs/source/release-notes/workarea-3-4-7.html.md +0 -162
- data/docs/source/release-notes/workarea-3-4-8.html.md +0 -95
- data/docs/source/release-notes/workarea-3-4-9.html.md +0 -135
- data/docs/source/release-notes.html.md +0 -261
- data/docs/source/search.html.erb +0 -34
- data/docs/source/shared/_header.erb +0 -61
- data/docs/source/shared/_svgs.erb +0 -17
- data/docs/source/style_guide/index.html.erb +0 -382
- data/docs/source/stylesheets/_base.scss +0 -125
- data/docs/source/stylesheets/_components.scss +0 -669
- data/docs/source/stylesheets/_helpers.scss +0 -10
- data/docs/source/stylesheets/_opinions.scss +0 -42
- data/docs/source/stylesheets/_settings.scss +0 -56
- data/docs/source/stylesheets/_typography.scss +0 -119
- data/docs/source/stylesheets/site.css.scss +0 -14
- data/docs/source/stylesheets/vendor/_avalanche.scss +0 -328
- data/docs/source/stylesheets/vendor/_normalize.scss +0 -341
- data/docs/source/stylesheets/vendor/highlight/_tomorrow_night_blue.scss +0 -75
- data/docs/source/upgrade-guides/workarea-3-4-0.html.md +0 -152
- data/docs/source/upgrade-guides.html.md +0 -18
- data/docs/workarea_renderer.rb +0 -8
- data/docs/yarn.lock +0 -2522
@@ -1,1005 +0,0 @@
|
|
1
|
-
---
|
2
|
-
title: Search
|
3
|
-
excerpt: Workarea applications persist model data to MongoDB, using it as the database of record. However, to provide near-real-time search, Workarea persists many of the same models to Elasticsearch, after first transforming them into a format suitable for se
|
4
|
-
---
|
5
|
-
|
6
|
-
# Search
|
7
|
-
|
8
|
-
Workarea applications persist model data to MongoDB, using it as the database of record. However, to provide near-real-time search, Workarea persists many of the same models to Elasticsearch, after first transforming them into a format suitable for search.
|
9
|
-
|
10
|
-
Workarea [callbacks workers](workers.html#callbacks-worker) enqueue in response to changes to Mongoid documents, and when run, these workers synchronize these data changes to Elasticsearch.
|
11
|
-
|
12
|
-
Workarea also provides query classes which encapsulate the complexity of the various search requests to Elasticsearch needed by Workarea applications. Each search query provides the search results for a given set of query parameters. Results are Mongoid models, initialized directly from a serialized copy in Elasticsearch, so it is not necessary to query MongoDB for results.
|
13
|
-
|
14
|
-
## Client & Server(s)
|
15
|
-
|
16
|
-
Workarea uses a [Ruby client](http://www.rubydoc.info/gems/elasticsearch-transport/5.0.4/Elasticsearch/Transport/Client) to communicate with an Elasticsearch [cluster](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/_basic_concepts.html#_cluster). Workarea Hosting provisions each cloud environment with a cluster. You must provision your own cluster for local environments.
|
17
|
-
|
18
|
-
The client instance, accessed as `Workarea.elasticsearch`, provides a [Ruby implementation](http://www.rubydoc.info/gems/elasticsearch-api/5.0.4/Elasticsearch/API) of the [Elasticsearch REST APIs](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/index.html).
|
19
|
-
|
20
|
-
```ruby
|
21
|
-
Workarea.elasticsearch.class
|
22
|
-
# => Elasticsearch::Transport::Client
|
23
|
-
```
|
24
|
-
|
25
|
-
In normal operation, you will not use the client directly (favoring higher level APIs), however, direct access to the client is useful for debugging and other secondary use cases. The example below uses the client to print a simple status report for the entire cluster.
|
26
|
-
|
27
|
-
```ruby
|
28
|
-
puts Workarea.elasticsearch.cat.health(v: true, h: %w(cluster status))
|
29
|
-
# cluster status
|
30
|
-
# elasticsearch yellow
|
31
|
-
```
|
32
|
-
|
33
|
-
## Documents, Indexes, Types & Mappings
|
34
|
-
|
35
|
-
### Types
|
36
|
-
|
37
|
-
Elasticsearch uses [types](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/_basic_concepts.html#_type) to categorize documents according to their fields, or [mappings](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/mapping.html). Workarea uses four types out of the box:
|
38
|
-
|
39
|
-
- admin
|
40
|
-
- help
|
41
|
-
- storefront
|
42
|
-
- category
|
43
|
-
|
44
|
-
Workarea uses documents of type _category_ to index category queries for use with the [percolate query](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/query-dsl-percolate-query.html), which can find the matching categories for a given product document. Because category documents are indexed and queried differently than the others, I do not cover them in this guide.
|
45
|
-
|
46
|
-
### Indexes
|
47
|
-
|
48
|
-
Documents of type _admin_, _help_, and _storefront_ are stored in separate indexes. Workarea applications use a varying number of Elasticsearch indexes. An index exists for each combination of site name, Rails environment, locale, and Elasticsearch document type. <sup><a href="#notes" id="note-1-context">[1]</a></sup>
|
49
|
-
|
50
|
-
For example, the indexes for a simple development application could be as follows.
|
51
|
-
|
52
|
-
- board\_games\_direct\_development\_en\_admin
|
53
|
-
- board\_games\_direct\_development\_en\_help
|
54
|
-
- board\_games\_direct\_development\_en\_storefront
|
55
|
-
|
56
|
-
Meanwhile, the following list of indexes could be used in an application with multiple site names (requires the [Multi Site](https://stash.tools.weblinc.com/projects/WL/repos/workarea-multi-site/browse) plugin), environments, and locales.
|
57
|
-
|
58
|
-
- board\_games\_direct\_development\_en\_admin
|
59
|
-
- board\_games\_direct\_development\_en\_help
|
60
|
-
- board\_games\_direct\_development\_en\_storefront
|
61
|
-
- board\_games\_direct\_development\_es\_admin
|
62
|
-
- board\_games\_direct\_development\_es\_help
|
63
|
-
- board\_games\_direct\_development\_es\_storefront
|
64
|
-
- board\_games\_direct\_production\_en\_admin
|
65
|
-
- board\_games\_direct\_production\_en\_help
|
66
|
-
- board\_games\_direct\_production\_en\_storefront
|
67
|
-
- board\_games\_direct\_production\_es\_admin
|
68
|
-
- board\_games\_direct\_production\_es\_help
|
69
|
-
- board\_games\_direct\_production\_es\_storefront
|
70
|
-
- board\_games\_direct\_qa\_en\_admin
|
71
|
-
- board\_games\_direct\_qa\_en\_help
|
72
|
-
- board\_games\_direct\_qa\_en\_storefront
|
73
|
-
- board\_games\_direct\_qa\_es\_admin
|
74
|
-
- board\_games\_direct\_qa\_es\_help
|
75
|
-
- board\_games\_direct\_qa\_es\_storefront
|
76
|
-
- board\_games\_direct\_staging\_en\_admin
|
77
|
-
- board\_games\_direct\_staging\_en\_help
|
78
|
-
- board\_games\_direct\_staging\_en\_storefront
|
79
|
-
- board\_games\_direct\_staging\_es\_admin
|
80
|
-
- board\_games\_direct\_staging\_es\_help
|
81
|
-
- board\_games\_direct\_staging\_es\_storefront
|
82
|
-
- party\_games\_direct\_development\_en\_admin
|
83
|
-
- party\_games\_direct\_development\_en\_help
|
84
|
-
- party\_games\_direct\_development\_en\_storefront
|
85
|
-
- party\_games\_direct\_development\_es\_admin
|
86
|
-
- party\_games\_direct\_development\_es\_help
|
87
|
-
- party\_games\_direct\_development\_es\_storefront
|
88
|
-
- party\_games\_direct\_production\_en\_admin
|
89
|
-
- party\_games\_direct\_production\_en\_help
|
90
|
-
- party\_games\_direct\_production\_en\_storefront
|
91
|
-
- party\_games\_direct\_production\_es\_admin
|
92
|
-
- party\_games\_direct\_production\_es\_help
|
93
|
-
- party\_games\_direct\_production\_es\_storefront
|
94
|
-
- party\_games\_direct\_qa\_en\_admin
|
95
|
-
- party\_games\_direct\_qa\_en\_help
|
96
|
-
- party\_games\_direct\_qa\_en\_storefront
|
97
|
-
- party\_games\_direct\_qa\_es\_admin
|
98
|
-
- party\_games\_direct\_qa\_es\_help
|
99
|
-
- party\_games\_direct\_qa\_es\_storefront
|
100
|
-
- party\_games\_direct\_staging\_en\_admin
|
101
|
-
- party\_games\_direct\_staging\_en\_help
|
102
|
-
- party\_games\_direct\_staging\_en\_storefront
|
103
|
-
- party\_games\_direct\_staging\_es\_admin
|
104
|
-
- party\_games\_direct\_staging\_es\_help
|
105
|
-
- party\_games\_direct\_staging\_es\_storefront
|
106
|
-
|
107
|
-
### Mappings
|
108
|
-
|
109
|
-
Elasticsearch mappings are typically declared for an index when the index is created, however, the mapping may be extended at index time, such as when an index's mapping includes [dynamic templates](https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-templates.html).
|
110
|
-
|
111
|
-
When creating a new index, Workarea looks for a configuration value declaring the mapping for that index. The configuration keys are named after the different document types. <sup><a href="#notes" id="note-2-context">[2]</a></sup> Each configured mapping includes _properties_ and _dynamic templates_.
|
112
|
-
|
113
|
-
For example, the default configuration of the mappings for _storefront_ indexes are shown below.
|
114
|
-
|
115
|
-
```ruby
|
116
|
-
config.elasticsearch_mappings.storefront = {
|
117
|
-
category: { properties: { query: { type: 'percolator' } } },
|
118
|
-
storefront: {
|
119
|
-
dynamic_templates: [
|
120
|
-
{
|
121
|
-
facets: {
|
122
|
-
path_match: 'facets.*',
|
123
|
-
mapping: { type: 'keyword' }
|
124
|
-
}
|
125
|
-
},
|
126
|
-
{
|
127
|
-
numeric: {
|
128
|
-
path_match: 'numeric.*',
|
129
|
-
mapping: { type: 'float' }
|
130
|
-
}
|
131
|
-
},
|
132
|
-
{
|
133
|
-
keywords: {
|
134
|
-
path_match: 'keywords.*',
|
135
|
-
mapping: { type: 'keyword' }
|
136
|
-
}
|
137
|
-
},
|
138
|
-
{
|
139
|
-
sorts: {
|
140
|
-
path_match: 'sorts.*',
|
141
|
-
mapping: { type: 'float' }
|
142
|
-
}
|
143
|
-
},
|
144
|
-
{
|
145
|
-
content: {
|
146
|
-
path_match: 'content.*',
|
147
|
-
mapping: { type: 'text', analyzer: 'text_analyzer' }
|
148
|
-
}
|
149
|
-
},
|
150
|
-
{
|
151
|
-
cache: {
|
152
|
-
path_match: 'cache.*',
|
153
|
-
mapping: { index: false }
|
154
|
-
}
|
155
|
-
}
|
156
|
-
],
|
157
|
-
properties: {
|
158
|
-
id: { type: 'keyword' },
|
159
|
-
type: { type: 'keyword' },
|
160
|
-
slug: { type: 'keyword' },
|
161
|
-
suggestion_content: { type: 'string', analyzer: 'text_analyzer' }
|
162
|
-
}
|
163
|
-
}
|
164
|
-
}
|
165
|
-
```
|
166
|
-
|
167
|
-
Because the storefront mappings depend heavily on dynamic templates, the method `Workarea::Search::Storefront.ensure_dynamic_mappings` is available, which creates a product document, indexes it, and then removes it. This process helps reduce errors in a new environment where the index-time mappings have not been created yet.
|
168
|
-
|
169
|
-
### Document Interface
|
170
|
-
|
171
|
-
The `Workarea::Elasticsearch::Document` module provides a Ruby interface to represent behavior shared by Elasticsearch documents of _all_ types. Each class that includes this module represents a _specific_ type. Calling `Document.all` returns a list of the more specific classes.
|
172
|
-
|
173
|
-
```
|
174
|
-
puts Workarea::Elasticsearch::Document.all
|
175
|
-
# Workarea::Search::Admin
|
176
|
-
# Workarea::Search::Help
|
177
|
-
# Workarea::Search::Storefront
|
178
|
-
```
|
179
|
-
|
180
|
-
The classes listed above are used almost exclusively for _type_ and _index_ level concerns (see below), while the descendants of these classes (covered under Search Models) are used primarily for _document_ level concerns. <sup><a href="#notes" id="note-3-context">[3]</a></sup>
|
181
|
-
|
182
|
-
These classes respond to `.type` and `.mappings`, which describe the type of documents for which they are responsible. (Note that `.mappings` returns the Workarea configuration, not the actual mappings on the index.)
|
183
|
-
|
184
|
-
```ruby
|
185
|
-
Workarea::Elasticsearch::Document.all.map(&:type)
|
186
|
-
# => [:admin, :help, :storefront]
|
187
|
-
|
188
|
-
pp Workarea::Search::Help.mappings
|
189
|
-
# {:help=>
|
190
|
-
# {:dynamic_templates=>
|
191
|
-
# [{:facet_values=>
|
192
|
-
# {:path_match=>"facets.*",
|
193
|
-
# :mapping=>{:type=>"string", :analyzer=>"keyword"}}}],
|
194
|
-
# :properties=>
|
195
|
-
# {:id=>{:type=>"string", :index=>"not_analyzed"},
|
196
|
-
# :name=>{:type=>"string", :analyzer=>"text_analyzer"},
|
197
|
-
# :body=>{:type=>"string", :analyzer=>"text_analyzer"},
|
198
|
-
# :created_at=>{:type=>"date"}}}}
|
199
|
-
```
|
200
|
-
|
201
|
-
The following methods are used to create, delete, and reset all indexes for the particular document type. Remember that each document type may be stored on many indexes depending on the number of sites, environments, and locales.
|
202
|
-
|
203
|
-
- `.create_indexes!`
|
204
|
-
- `.delete_indexes!`
|
205
|
-
- `.reset_indexes!`
|
206
|
-
|
207
|
-
Every Elasticsearch document class has a <dfn>current index</dfn>. The example below demonstrates the current index is determined by the combination of current site name, Rails environment, locale, and document type.
|
208
|
-
|
209
|
-
```ruby
|
210
|
-
Workarea::Search::Storefront.current_index.name
|
211
|
-
# => "board_games_direct_development_en_storefront"
|
212
|
-
|
213
|
-
Workarea::Search::Storefront.current_index.url
|
214
|
-
# => "http://localhost:9200/board_games_direct_development_en_storefront"
|
215
|
-
|
216
|
-
Workarea.config.site_name
|
217
|
-
# => "Board Games Direct"
|
218
|
-
|
219
|
-
Rails.env
|
220
|
-
# => "development"
|
221
|
-
|
222
|
-
I18n.locale
|
223
|
-
# => :en
|
224
|
-
|
225
|
-
Workarea::Search::Storefront.type
|
226
|
-
# => :storefront
|
227
|
-
```
|
228
|
-
|
229
|
-
The current index is an instance of `Workarea::Elasticsearch::Index`, another abstraction provided by Workarea.
|
230
|
-
|
231
|
-
```ruby
|
232
|
-
Workarea::Search::Storefront.current_index.class
|
233
|
-
# => Workarea::Elasticsearch::Index
|
234
|
-
```
|
235
|
-
|
236
|
-
I do not cover this abstraction in detail because it is used internally and rarely invoked by application code. A Search model initializes instances of `Index` when needed and delegates index operations to its `current_index`.
|
237
|
-
|
238
|
-
## Indexing
|
239
|
-
|
240
|
-
Most search indexing is performed by [callbacks workers](workers.html#callbacks-worker) running in response to changes to application documents, and by workers run [on a schedule](workers.html#sidekiq-cron-job). Internally, workers use search models to transform the affected application documents into search documents, which involves serializing in-memory objects into strings. The search models then index the transformed documents into Elasticsearch.
|
241
|
-
|
242
|
-
To a lesser extent, rake tasks and seeds are also used to index documents for search.
|
243
|
-
|
244
|
-
### Workers
|
245
|
-
|
246
|
-
Various workers are used to index documents into Elasticsearch. Many of these are callbacks workers that run in response to life cycle changes on application documents (Mongoid documents) and use search models to forward Mongoid changes to Elasticsearch.
|
247
|
-
|
248
|
-
For example, review the implementation of `Workarea::IndexPage`, below.
|
249
|
-
|
250
|
-
```ruby
|
251
|
-
module Workarea
|
252
|
-
class IndexPage
|
253
|
-
include Sidekiq::Worker
|
254
|
-
include Sidekiq::CallbacksWorker
|
255
|
-
|
256
|
-
sidekiq_options(
|
257
|
-
enqueue_on: { Content::Page => [:save, :destroy] },
|
258
|
-
unique: :until_executing
|
259
|
-
)
|
260
|
-
|
261
|
-
def perform(id)
|
262
|
-
page = Content::Page.find(id)
|
263
|
-
Search::Storefront::Page.new(page).save
|
264
|
-
rescue Mongoid::Errors::DocumentNotFound
|
265
|
-
Search::Storefront::Page.new(
|
266
|
-
Content::Page.new(id: id)
|
267
|
-
).destroy
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
271
|
-
```
|
272
|
-
|
273
|
-
when a `Workarea::Content::Page` is saved or destroyed, `Workarea::IndexPage` is enqueued with the id of the saved or destroyed content page. When this worker runs, it looks up the affected content page and creates an instance of `Search::Storefront::Page` from it. Then the worker uses `Search::Storefront::Page#save` or `Search::Storefront::Page#destroy` to create and index, or delete, the corresponding search document.
|
274
|
-
|
275
|
-
The `Workarea::IndexAdminSearch` worker follows the same pattern, but it is enqueued on _save_, _touch_, or _destroy_ of any application document. The worker uses the `Search::Admin.for` factory to initialize the correct search model from the affected application document.
|
276
|
-
|
277
|
-
The Admin UI inlines `IndexAdminSearch` for the duration of each Admin request so that model changes applied through the Admin UI are applied inline rather than asynchronously.
|
278
|
-
|
279
|
-
```ruby
|
280
|
-
module Workarea
|
281
|
-
module Admin
|
282
|
-
class ApplicationController < Workarea::ApplicationController
|
283
|
-
# ...
|
284
|
-
around_action :inline_search_indexing
|
285
|
-
|
286
|
-
# ...
|
287
|
-
|
288
|
-
private
|
289
|
-
|
290
|
-
# ...
|
291
|
-
|
292
|
-
def inline_search_indexing
|
293
|
-
Sidekiq::Callbacks.inline(IndexAdminSearch) { yield }
|
294
|
-
end
|
295
|
-
|
296
|
-
# ...
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
```
|
301
|
-
|
302
|
-
Some callbacks workers delegate to other workers rather than using a search model directly. The workers that are delegated _to_ implement a `.perform` class method, which typically receives the affected Mongoid model instance (rather than an id) as its argument.
|
303
|
-
|
304
|
-
For example, changes to catalog variants and product images cause the parent products to be re-indexed into the Storefront indexes. To do so, the `Workarea::IndexProductChildren` worker determines which parent product is affected and uses `IndexProduct.perform` to re-index the product.
|
305
|
-
|
306
|
-
```ruby
|
307
|
-
module Workarea
|
308
|
-
class IndexProductChildren
|
309
|
-
include Sidekiq::Worker
|
310
|
-
include Sidekiq::CallbacksWorker
|
311
|
-
|
312
|
-
sidekiq_options(
|
313
|
-
enqueue_on: {
|
314
|
-
Catalog::Variant => [:save, :destroy],
|
315
|
-
Catalog::ProductImage => [:save, :destroy],
|
316
|
-
with: -> { [_parent.id.to_s] }
|
317
|
-
},
|
318
|
-
unique: :until_executing
|
319
|
-
)
|
320
|
-
|
321
|
-
def perform(id)
|
322
|
-
product = Catalog::Product.find(id) rescue nil
|
323
|
-
IndexProduct.perform(product) if product.present?
|
324
|
-
end
|
325
|
-
end
|
326
|
-
end
|
327
|
-
```
|
328
|
-
|
329
|
-
Similarly, changes to catalog categories cause affected products to be re-indexed. The `Workarea::IndexCategoryChanges` determines which products are affected and uses `BulkIndexProducts.perform` to re-index them in a single request.
|
330
|
-
|
331
|
-
```ruby
|
332
|
-
module Workarea
|
333
|
-
class IndexCategoryChanges
|
334
|
-
include Sidekiq::Worker
|
335
|
-
include Sidekiq::CallbacksWorker
|
336
|
-
|
337
|
-
sidekiq_options(
|
338
|
-
enqueue_on: { Catalog::Category => :save, with: -> { [changes] } },
|
339
|
-
ignore_if: -> { changes['product_ids'].blank? },
|
340
|
-
unique: :until_executing
|
341
|
-
)
|
342
|
-
|
343
|
-
def perform(changes)
|
344
|
-
if changes['product_ids'].present?
|
345
|
-
previous_ids = changes['product_ids'].first || []
|
346
|
-
new_ids = changes['product_ids'].second || []
|
347
|
-
|
348
|
-
require_index_ids = (previous_ids - new_ids) + (new_ids - previous_ids)
|
349
|
-
BulkIndexProducts.perform(require_index_ids)
|
350
|
-
end
|
351
|
-
end
|
352
|
-
end
|
353
|
-
end
|
354
|
-
```
|
355
|
-
|
356
|
-
Other indexing workers run on a schedule instead of in response to model changes. Examples are `Workarea::CleanOrders` and `Workarea::KeepProductIndexFresh`.
|
357
|
-
|
358
|
-
Finally, some workers are run neither as callbacks nor on a schedule. These workers must be run manually, usually from another worker. Examples are `Workarea::BulkIndexProducts` and `Workarea::BulkIndexSearches`.
|
359
|
-
|
360
|
-
### Search Models
|
361
|
-
|
362
|
-
Search models are initialized from Mongoid documents and can save and destroy corresponding search documents to and from relevant Elasticsearch indexes. Search documents are responsible for transforming Mongoid documents into search documents, and in the process of doing so, they serialize the entire Mongoid document for storage into Elasticsearch.
|
363
|
-
|
364
|
-
#### Initializing
|
365
|
-
|
366
|
-
`Workarea::Search::Admin` is an abstract superclass whose subclasses are search models that index documents of type _admin_.
|
367
|
-
|
368
|
-
```ruby
|
369
|
-
puts Workarea::Search::Admin.descendants
|
370
|
-
# Workarea::Search::Admin::CatalogCategory
|
371
|
-
# Workarea::Search::Admin::CatalogProduct
|
372
|
-
# Workarea::Search::Admin::Content
|
373
|
-
# Workarea::Search::Admin::ContentAsset
|
374
|
-
# Workarea::Search::Admin::ContentPage
|
375
|
-
# Workarea::Search::Admin::InventorySku
|
376
|
-
# Workarea::Search::Admin::Navigation
|
377
|
-
# Workarea::Search::Admin::NavigationMenu
|
378
|
-
# Workarea::Search::Admin::Order
|
379
|
-
# Workarea::Search::Admin::PaymentTransaction
|
380
|
-
# Workarea::Search::Admin::PricingDiscount
|
381
|
-
# Workarea::Search::Admin::PricingSku
|
382
|
-
# Workarea::Search::Admin::Release
|
383
|
-
# Workarea::Search::Admin::User
|
384
|
-
```
|
385
|
-
|
386
|
-
The factory method `Workarea::Search::Admin.for` will create an instance of one of the above search models for a given Mongoid model (see example in workers section, above).
|
387
|
-
|
388
|
-
Similarly, `Workarea::Search::Storefront` is an abstract superclass whose subclasses are search models that index documents of type _storefront_.
|
389
|
-
|
390
|
-
```ruby
|
391
|
-
puts Workarea::Search::Storefront.descendants
|
392
|
-
# Workarea::Search::Storefront::Category
|
393
|
-
# Workarea::Search::Storefront::Page
|
394
|
-
# Workarea::Search::Storefront::Product
|
395
|
-
# Workarea::Search::Storefront::Search
|
396
|
-
```
|
397
|
-
|
398
|
-
`Workarea::Search::Help` has no descendants and is used as the search model for documents of type _help_.
|
399
|
-
|
400
|
-
```ruby
|
401
|
-
Workarea::Search::Help.descendants
|
402
|
-
# => []
|
403
|
-
```
|
404
|
-
|
405
|
-
Initialize a search model with an application document (a Mongoid model).
|
406
|
-
|
407
|
-
```ruby
|
408
|
-
product = Workarea::Catalog::Product.create!(name: 'Escape the Room')
|
409
|
-
|
410
|
-
product_admin_search_model = Workarea::Search::Admin::CatalogProduct.new(product)
|
411
|
-
|
412
|
-
# or use the factory for 'admin' documents
|
413
|
-
product_admin_search_model = Workarea::Search::Admin.for(product)
|
414
|
-
|
415
|
-
product_admin_search_model.class
|
416
|
-
# => Workarea::Search::Admin::CatalogProduct
|
417
|
-
```
|
418
|
-
|
419
|
-
Search models return a `type`, which describes the Mongoid document type rather than the Elasticsearch document type. In the case of Admin and Storefront search models, many different Mongoid types map to the same Elasticsearch types.
|
420
|
-
|
421
|
-
```ruby
|
422
|
-
# Mongoid "type"
|
423
|
-
product_admin_search_model.type
|
424
|
-
# => "product"
|
425
|
-
|
426
|
-
# Elasticsearch "type"
|
427
|
-
product_admin_search_model.class.type
|
428
|
-
# => :admin
|
429
|
-
```
|
430
|
-
|
431
|
-
The following examples use the same Mongoid model from above to create and explore a Storefront search model.
|
432
|
-
|
433
|
-
```ruby
|
434
|
-
product_storefront_search_model = Workarea::Search::Storefront::Product.new(product)
|
435
|
-
|
436
|
-
product_storefront_search_model.class
|
437
|
-
# => Workarea::Search::Storefront::Product
|
438
|
-
|
439
|
-
product_storefront_search_model.type
|
440
|
-
# => "product"
|
441
|
-
|
442
|
-
product_storefront_search_model.class.type
|
443
|
-
# => :storefront
|
444
|
-
```
|
445
|
-
|
446
|
-
A search model provides access to the original Mongoid model.
|
447
|
-
|
448
|
-
```ruby
|
449
|
-
product_storefront_search_model.model.class
|
450
|
-
# => Workarea::Catalog::Product
|
451
|
-
|
452
|
-
product_storefront_search_model.model.name
|
453
|
-
# => "Escape the Room"
|
454
|
-
|
455
|
-
product_storefront_search_model.model.id
|
456
|
-
# => "273E095F5A"
|
457
|
-
```
|
458
|
-
|
459
|
-
Be aware that a search model and its originating Mongoid model have different, albeit similar, IDs.
|
460
|
-
|
461
|
-
```ruby
|
462
|
-
product_storefront_search_model.id
|
463
|
-
# => "product-273E095F5A"
|
464
|
-
|
465
|
-
product_storefront_search_model.catalog_id
|
466
|
-
# => "273E095F5A"
|
467
|
-
|
468
|
-
product_storefront_search_model.model.id
|
469
|
-
# => "273E095F5A"
|
470
|
-
```
|
471
|
-
|
472
|
-
#### Saving & Destroying
|
473
|
-
|
474
|
-
Use the `save` method to create and index a search document, and use the `destroy` method to delete a search document.
|
475
|
-
|
476
|
-
```ruby
|
477
|
-
product_storefront_search_model.save
|
478
|
-
```
|
479
|
-
|
480
|
-
```ruby
|
481
|
-
product_storefront_search_model.destroy
|
482
|
-
```
|
483
|
-
|
484
|
-
These operations may affect multiple documents (in multiple indexes) if the application has multiple locales. These methods save or destroy one document per locale.
|
485
|
-
|
486
|
-
#### Creating Search Documents
|
487
|
-
|
488
|
-
When search models `save` documents, they must first create a document that is suitable for Elasticsearch. They do so by transforming the Mongoid model, and in many cases, aggregating multiple related models. For example, a searchable product requires catalog, pricing, and inventory data. Each search model implements `as_document` and `as_bulk_document` for this purpose.
|
489
|
-
|
490
|
-
The following examples create Admin and Storefront search documents from the same Mongoid source document. Notice how the fields of each search document are different.
|
491
|
-
|
492
|
-
```ruby
|
493
|
-
pp product_admin_search_model.as_document
|
494
|
-
# {:id=>"product-273E095F5A",
|
495
|
-
# :name=>"Escape the Room",
|
496
|
-
# :facets=>
|
497
|
-
# {:status=>"inactive",
|
498
|
-
# :type=>"product",
|
499
|
-
# :tags=>[],
|
500
|
-
# :upcoming_changes=>[],
|
501
|
-
# :category=>"Automotive",
|
502
|
-
# :category_id=>
|
503
|
-
# ["5995eaf007dd42106a36021a",
|
504
|
-
# "5995eaf007dd42106a360218",
|
505
|
-
# "5995eaf007dd42106a360216",
|
506
|
-
# "5995eaf007dd42106a360220",
|
507
|
-
# "5995eaf007dd42106a360214",
|
508
|
-
# "5995eaf007dd42106a360224"],
|
509
|
-
# :on_sale=>false,
|
510
|
-
# :issues=>["No Images", "No Description", "No Variants"],
|
511
|
-
# :template=>"generic"},
|
512
|
-
# :created_at=>Wed, 23 Aug 2017 18:46:23 UTC +00:00,
|
513
|
-
# :updated_at=>Wed, 23 Aug 2017 18:46:23 UTC +00:00,
|
514
|
-
# :search_text=>["273E095F5A", "Escape the Room", "product"],
|
515
|
-
# :jump_to_text=>"Escape the Room (273E095F5A)",
|
516
|
-
# :jump_to_search_text=>["273E095F5A", "Escape the Room", "product"],
|
517
|
-
# :jump_to_position=>3,
|
518
|
-
# :jump_to_route_helper=>"catalog_product_path",
|
519
|
-
# :jump_to_param=>"escape-the-room",
|
520
|
-
# :releasable=>true}
|
521
|
-
```
|
522
|
-
|
523
|
-
```ruby
|
524
|
-
pp product_storefront_search_model.as_document
|
525
|
-
# {:id=>"product-273E095F5A",
|
526
|
-
# :type=>"product",
|
527
|
-
# :slug=>"escape-the-room",
|
528
|
-
# :active=>{:now=>false},
|
529
|
-
# :suggestion_content=>
|
530
|
-
# "Escape the Room Outdoors, Jewelry, Sports, Tools, Movies, Grocery ",
|
531
|
-
# :created_at=>Wed, 23 Aug 2017 18:46:23 UTC +00:00,
|
532
|
-
# :updated_at=>Wed, 23 Aug 2017 18:46:23 UTC +00:00,
|
533
|
-
# :facets=>
|
534
|
-
# {:category=>"Automotive",
|
535
|
-
# :category_id=>
|
536
|
-
# ["5995eaf007dd42106a36021a",
|
537
|
-
# "5995eaf007dd42106a360218",
|
538
|
-
# "5995eaf007dd42106a360216",
|
539
|
-
# "5995eaf007dd42106a360220",
|
540
|
-
# "5995eaf007dd42106a360214",
|
541
|
-
# "5995eaf007dd42106a360224"],
|
542
|
-
# :on_sale=>false},
|
543
|
-
# :numeric=>{:price=>[0.0], :inventory=>0, :variant_count=>0},
|
544
|
-
# :keywords=>{:catalog_id=>"273E095F5A", :sku=>[]},
|
545
|
-
# :sorts=>
|
546
|
-
# {BSON::ObjectId('5995eaf007dd42106a360214')=>nil,
|
547
|
-
# BSON::ObjectId('5995eaf007dd42106a360216')=>nil,
|
548
|
-
# BSON::ObjectId('5995eaf007dd42106a360218')=>nil,
|
549
|
-
# BSON::ObjectId('5995eaf007dd42106a36021a')=>nil,
|
550
|
-
# BSON::ObjectId('5995eaf007dd42106a360220')=>nil,
|
551
|
-
# BSON::ObjectId('5995eaf007dd42106a360224')=>nil,
|
552
|
-
# :price=>0.0,
|
553
|
-
# :orders_score=>0.0,
|
554
|
-
# :views_score=>0.0},
|
555
|
-
# :content=>
|
556
|
-
# {:name=>"Escape the Room",
|
557
|
-
# :category_names=>"Outdoors, Jewelry, Sports, Tools, Movies, Grocery",
|
558
|
-
# :description=>"",
|
559
|
-
# :details=>" ",
|
560
|
-
# :facets=>""},
|
561
|
-
# :cache=>
|
562
|
-
# {:image=>"/product_images/placeholder/small_thumb.jpg?c=1502997231",
|
563
|
-
# :pricing=>[],
|
564
|
-
# :inventory=>[]}}
|
565
|
-
```
|
566
|
-
|
567
|
-
The fields of a search document should match the mapping for its type. Some fields appear in the mapping explicitly, as properties, while other match implicitly, via dynamic templates.
|
568
|
-
|
569
|
-
Some fields are used only for storage, not search. For example, the _cache.image_, _cache.pricing_, and _cache.inventory_ fields above are all configured to be stored but not indexed.
|
570
|
-
|
571
|
-
```ruby
|
572
|
-
config.elasticsearch_mappings.storefront = {
|
573
|
-
# ...
|
574
|
-
storefront: {
|
575
|
-
dynamic_templates: [
|
576
|
-
# ...
|
577
|
-
{
|
578
|
-
cache: {
|
579
|
-
path_match: 'cache.*',
|
580
|
-
mapping: { index: false }
|
581
|
-
}
|
582
|
-
}
|
583
|
-
],
|
584
|
-
properties: {
|
585
|
-
# ...
|
586
|
-
}
|
587
|
-
}
|
588
|
-
}
|
589
|
-
```
|
590
|
-
|
591
|
-
Cached fields are used when loading results to avoid additional queries to MongoDB.
|
592
|
-
|
593
|
-
Much of each search model's implementation is made up of methods used to compose the hash returned from _as\_document_.
|
594
|
-
|
595
|
-
#### Transformation "Helpers"
|
596
|
-
|
597
|
-
Workarea provides several classes to help construct the `as_document` hash.
|
598
|
-
|
599
|
-
`Workarea::Search::Admin::Releasable` is included in search models for releasable models. It includes additional fields in the `as_document` hash related to releases. The following example lists classes that include this module.
|
600
|
-
|
601
|
-
```ruby
|
602
|
-
releasables = Workarea::Search::Admin.descendants.select do |klass|
|
603
|
-
klass.included_modules.include?(Workarea::Search::Admin::Releasable)
|
604
|
-
end
|
605
|
-
puts releasables.map(&:to_s).sort
|
606
|
-
# Workarea::Search::Admin::CatalogCategory
|
607
|
-
# Workarea::Search::Admin::CatalogProduct
|
608
|
-
# Workarea::Search::Admin::Content
|
609
|
-
# Workarea::Search::Admin::ContentPage
|
610
|
-
# Workarea::Search::Admin::NavigationMenu
|
611
|
-
# Workarea::Search::Admin::PricingDiscount
|
612
|
-
# Workarea::Search::Admin::PricingSku
|
613
|
-
```
|
614
|
-
|
615
|
-
Several other <abbr title="plain old Ruby object">PORO</abbr>s exist to help construct specific values for the as\_document hash.
|
616
|
-
|
617
|
-
- `Workarea::Search::FacetValues`
|
618
|
-
- `Workarea::Search::HashText`
|
619
|
-
- `Workarea::Search::OrderText`
|
620
|
-
- `Workarea::Search::UserText`
|
621
|
-
|
622
|
-
### Serialization & De-Serialization
|
623
|
-
|
624
|
-
Workarea provides `Workarea::Elasticsearch::Serializer` for serializing in-memory models into strings suitable for storage in Elasticsearch, and for de-serializing those strings back into models without needing to query MongoDB.
|
625
|
-
|
626
|
-
```ruby
|
627
|
-
product = Workarea::Catalog::Product.first
|
628
|
-
|
629
|
-
product.class
|
630
|
-
# => Workarea::Catalog::Product
|
631
|
-
|
632
|
-
product.id
|
633
|
-
# => "006CBBCD90"
|
634
|
-
|
635
|
-
product.name
|
636
|
-
# => "Fantastic Linen Pants"
|
637
|
-
```
|
638
|
-
|
639
|
-
Serialization passes the object through `Mongoid::Document.as_document` (if a Mongoid document), then `Marshal.dump`, and finally `Base64.encode64`.
|
640
|
-
|
641
|
-
```ruby
|
642
|
-
serialized_product = Workarea::Elasticsearch::Serializer.serialize(product)
|
643
|
-
|
644
|
-
serialized_product.class
|
645
|
-
# => Hash
|
646
|
-
|
647
|
-
serialized_product['model_class']
|
648
|
-
# => "Workarea::Catalog::Product"
|
649
|
-
|
650
|
-
serialized_product['model']
|
651
|
-
# => "BAhDOhNCU09OOjpEb2N1bWVudHsVSSIIX2lkBjoGRVRJIg8wMDZDQkJDRDkw...
|
652
|
-
```
|
653
|
-
|
654
|
-
De-serialization reverses the process, passing the string through `Base64.decode64`, then `Marshal.load`, and finally `Mongoid::Factory.from_db` to re-create the Mongoid document instance.
|
655
|
-
|
656
|
-
```ruby
|
657
|
-
deserialized_product = Workarea::Elasticsearch::Serializer.deserialize(serialized_product)
|
658
|
-
|
659
|
-
deserialized_product.class
|
660
|
-
# => Workarea::Catalog::Product
|
661
|
-
|
662
|
-
deserialized_product.id
|
663
|
-
# => "006CBBCD90"
|
664
|
-
|
665
|
-
deserialized_product.name
|
666
|
-
# => "Fantastic Linen Pants"
|
667
|
-
```
|
668
|
-
|
669
|
-
### Rake Tasks
|
670
|
-
|
671
|
-
Workarea provides several Rake tasks to manually re-index all search indexes or indexes for particular document types. The tasks are defined in `workarea-core/lib/tasks/search.rake`.
|
672
|
-
|
673
|
-
You can run the tasks as commands.
|
674
|
-
|
675
|
-
```bash
|
676
|
-
$ bin/rails workarea:search_index:all
|
677
|
-
```
|
678
|
-
|
679
|
-
```bash
|
680
|
-
$ bin/rails workarea:search_index:admin
|
681
|
-
```
|
682
|
-
|
683
|
-
```bash
|
684
|
-
$ bin/rails workarea:search_index:storefront
|
685
|
-
```
|
686
|
-
|
687
|
-
```bash
|
688
|
-
$ bin/rails workarea:search_index:help
|
689
|
-
```
|
690
|
-
|
691
|
-
Or invoke the tasks programatically.
|
692
|
-
|
693
|
-
```ruby
|
694
|
-
Rake::Task['workarea:search_index:all'].invoke
|
695
|
-
```
|
696
|
-
|
697
|
-
```ruby
|
698
|
-
Rake::Task['workarea:search_index:admin'].invoke
|
699
|
-
```
|
700
|
-
|
701
|
-
```ruby
|
702
|
-
Rake::Task['workarea:search_index:storefront'].invoke
|
703
|
-
```
|
704
|
-
|
705
|
-
```ruby
|
706
|
-
Rake::Task['workarea:search_index:help'].invoke
|
707
|
-
```
|
708
|
-
|
709
|
-
Regardless of how you execute them, these tasks each inline all Sidekiq workers for the duration of the task. As of Workarea 3.3, you can prevent this behavior by setting the environment variable `INLINE` to `false`. For example:
|
710
|
-
|
711
|
-
```bash
|
712
|
-
$ INLINE=false bin/rails workarea:search_index:all
|
713
|
-
```
|
714
|
-
|
715
|
-
### Seeds
|
716
|
-
|
717
|
-
Running seeds drops all MongoDB and Elasticsearch data for the current environment and primes both databases with data. Running seeds therefore resets all Elasticsearch indexes.
|
718
|
-
|
719
|
-
You can run seeds as a command.
|
720
|
-
|
721
|
-
```bash
|
722
|
-
$ bin/rails db:seed
|
723
|
-
```
|
724
|
-
|
725
|
-
Or programatically.
|
726
|
-
|
727
|
-
```ruby
|
728
|
-
Workarea::Seeds.run
|
729
|
-
```
|
730
|
-
|
731
|
-
## Search Queries
|
732
|
-
|
733
|
-
Workarea provides a variety of query classes which are responsible for complicated reads. This includes Elasticsearch searches, for which Workarea provides a variety of search queries.
|
734
|
-
|
735
|
-
Search queries are initialized with params and construct and perform an [Elasticsearch request body search](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/search-request-body.html). The query provides access to the raw Elasticsearch response in addition to "loaded" results, which returns the results as Mongoid documents, initialized from the serialized model cache within each Elasticsearch document.
|
736
|
-
|
737
|
-
Each search query instance therefore represents the Elasticsearch request and response for a given set of params. UI code often wraps a query instance in a view model and presents the results.
|
738
|
-
|
739
|
-
### Types & Initialization
|
740
|
-
|
741
|
-
Search queries are classes that include `Workarea::Search::Query`. The following example introspects the Ruby object space for search query classes.
|
742
|
-
|
743
|
-
```ruby
|
744
|
-
searches = ObjectSpace.each_object(Class).select do |klass|
|
745
|
-
klass.included_modules.include?(Workarea::Search::Query)
|
746
|
-
end
|
747
|
-
puts searches.map(&:to_s).sort
|
748
|
-
# Workarea::Search::AdminAssets
|
749
|
-
# Workarea::Search::AdminCategories
|
750
|
-
# Workarea::Search::AdminDiscounts
|
751
|
-
# Workarea::Search::AdminInventorySkus
|
752
|
-
# Workarea::Search::AdminOrders
|
753
|
-
# Workarea::Search::AdminPages
|
754
|
-
# Workarea::Search::AdminPaymentTransactions
|
755
|
-
# Workarea::Search::AdminPricingSkus
|
756
|
-
# Workarea::Search::AdminProducts
|
757
|
-
# Workarea::Search::AdminReleasables
|
758
|
-
# Workarea::Search::AdminSearch
|
759
|
-
# Workarea::Search::AdminUsers
|
760
|
-
# Workarea::Search::Categorization
|
761
|
-
# Workarea::Search::CategoryBrowse
|
762
|
-
# Workarea::Search::HelpSearch
|
763
|
-
# Workarea::Search::ProductSearch
|
764
|
-
# Workarea::Search::RelatedHelp
|
765
|
-
# Workarea::Search::RelatedProducts
|
766
|
-
# Workarea::Search::SearchSuggestions
|
767
|
-
```
|
768
|
-
|
769
|
-
Each search query searches for results of a particular Elasticsearch document type. The following example groups the search queries by type.
|
770
|
-
|
771
|
-
```ruby
|
772
|
-
pp searches.group_by(&:document)
|
773
|
-
# {Workarea::Search::Storefront=>
|
774
|
-
# [Workarea::Search::SearchSuggestions,
|
775
|
-
# Workarea::Search::RelatedProducts,
|
776
|
-
# Workarea::Search::ProductSearch,
|
777
|
-
# Workarea::Search::CategoryBrowse,
|
778
|
-
# Workarea::Search::Categorization],
|
779
|
-
# Workarea::Search::Help=>
|
780
|
-
# [Workarea::Search::RelatedHelp,
|
781
|
-
# Workarea::Search::HelpSearch],
|
782
|
-
# Workarea::Search::Admin=>
|
783
|
-
# [Workarea::Search::AdminUsers,
|
784
|
-
# Workarea::Search::AdminSearch,
|
785
|
-
# Workarea::Search::AdminReleasables,
|
786
|
-
# Workarea::Search::AdminProducts,
|
787
|
-
# Workarea::Search::AdminPricingSkus,
|
788
|
-
# Workarea::Search::AdminPaymentTransactions,
|
789
|
-
# Workarea::Search::AdminPages,
|
790
|
-
# Workarea::Search::AdminOrders,
|
791
|
-
# Workarea::Search::AdminInventorySkus,
|
792
|
-
# Workarea::Search::AdminDiscounts,
|
793
|
-
# Workarea::Search::AdminCategories,
|
794
|
-
# Workarea::Search::AdminAssets]}
|
795
|
-
```
|
796
|
-
|
797
|
-
Each search query instance is initialized with params.
|
798
|
-
|
799
|
-
```ruby
|
800
|
-
product_admin_search_query = Workarea::Search::AdminProducts.new(q: 'escape')
|
801
|
-
|
802
|
-
product_admin_search_query.class
|
803
|
-
# => Workarea::Search::AdminProducts
|
804
|
-
|
805
|
-
product_admin_search_query.class.document
|
806
|
-
# => Workarea::Search::Admin
|
807
|
-
|
808
|
-
product_admin_search_query.class.document.type
|
809
|
-
# => :admin
|
810
|
-
```
|
811
|
-
|
812
|
-
### Results
|
813
|
-
|
814
|
-
The `#total` and `#stats` methods return meta data about the results.
|
815
|
-
|
816
|
-
```ruby
|
817
|
-
product_admin_search_query.total
|
818
|
-
# => 1
|
819
|
-
|
820
|
-
pp product_admin_search_query.stats
|
821
|
-
# {"upcoming_changes"=>
|
822
|
-
# {"doc_count_error_upper_bound"=>0, "sum_other_doc_count"=>0, "buckets"=>[]},
|
823
|
-
# "template"=>
|
824
|
-
# {"doc_count_error_upper_bound"=>0,
|
825
|
-
# "sum_other_doc_count"=>0,
|
826
|
-
# "buckets"=>[{"key"=>"generic", "doc_count"=>1}]},
|
827
|
-
# "color"=>
|
828
|
-
# {"doc_count_error_upper_bound"=>0, "sum_other_doc_count"=>0, "buckets"=>[]},
|
829
|
-
# "size"=>
|
830
|
-
# {"doc_count_error_upper_bound"=>0, "sum_other_doc_count"=>0, "buckets"=>[]},
|
831
|
-
# "price"=>
|
832
|
-
# {"buckets"=>
|
833
|
-
# [{"key"=>"*-9.99", "to"=>9.99, "doc_count"=>0},
|
834
|
-
# {"key"=>"10.0-19.99", "from"=>10.0, "to"=>19.99, "doc_count"=>0},
|
835
|
-
# {"key"=>"20.0-29.99", "from"=>20.0, "to"=>29.99, "doc_count"=>0},
|
836
|
-
# {"key"=>"30.0-39.99", "from"=>30.0, "to"=>39.99, "doc_count"=>0},
|
837
|
-
# {"key"=>"40.0-49.99", "from"=>40.0, "to"=>49.99, "doc_count"=>0},
|
838
|
-
# {"key"=>"50.0-59.99", "from"=>50.0, "to"=>59.99, "doc_count"=>0},
|
839
|
-
# {"key"=>"60.0-69.99", "from"=>60.0, "to"=>69.99, "doc_count"=>0},
|
840
|
-
# {"key"=>"70.0-79.99", "from"=>70.0, "to"=>79.99, "doc_count"=>0},
|
841
|
-
# {"key"=>"80.0-89.99", "from"=>80.0, "to"=>89.99, "doc_count"=>0},
|
842
|
-
# {"key"=>"90.0-99.99", "from"=>90.0, "to"=>99.99, "doc_count"=>0},
|
843
|
-
# {"key"=>"100.0-*", "from"=>100.0, "doc_count"=>0}]},
|
844
|
-
# "type"=>
|
845
|
-
# {"doc_count_error_upper_bound"=>0,
|
846
|
-
# "sum_other_doc_count"=>0,
|
847
|
-
# "buckets"=>[{"key"=>"product", "doc_count"=>1}]},
|
848
|
-
# "issues"=>
|
849
|
-
# {"doc_count_error_upper_bound"=>0,
|
850
|
-
# "sum_other_doc_count"=>0,
|
851
|
-
# "buckets"=>
|
852
|
-
# [{"key"=>"No Description", "doc_count"=>1},
|
853
|
-
# {"key"=>"No Images", "doc_count"=>1},
|
854
|
-
# {"key"=>"No Variants", "doc_count"=>1}]},
|
855
|
-
# "status"=>
|
856
|
-
# {"doc_count_error_upper_bound"=>0,
|
857
|
-
# "sum_other_doc_count"=>0,
|
858
|
-
# "buckets"=>[{"key"=>"inactive", "doc_count"=>1}]},
|
859
|
-
# "tags"=>
|
860
|
-
# {"doc_count_error_upper_bound"=>0, "sum_other_doc_count"=>0, "buckets"=>[]}}
|
861
|
-
```
|
862
|
-
|
863
|
-
The `#response` method returns the raw response. Looking at the response, you can see the serialized model data stored within the Elasticsearch document source.
|
864
|
-
|
865
|
-
```ruby
|
866
|
-
pp product_admin_search_query.response
|
867
|
-
# {"took"=>23,
|
868
|
-
# "timed_out"=>false,
|
869
|
-
# "_shards"=>{"total"=>5, "successful"=>5, "failed"=>0},
|
870
|
-
# "hits"=>
|
871
|
-
# {"total"=>1,
|
872
|
-
# "max_score"=>nil,
|
873
|
-
# "hits"=>
|
874
|
-
# [{"_index"=>"try_search_development_en_admin",
|
875
|
-
# "_type"=>"admin",
|
876
|
-
# "_id"=>"product-273E095F5A",
|
877
|
-
# "_score"=>6.044283,
|
878
|
-
# "_source"=>
|
879
|
-
# {"id"=>"product-273E095F5A",
|
880
|
-
#
|
881
|
-
# # ...
|
882
|
-
#
|
883
|
-
# "model_class"=>"Workarea::Catalog::Product",
|
884
|
-
# "model"=>
|
885
|
-
# "BAhDOhNCU09OOjpEb2N1bWVudHsSSSIIX2lkBjoGRVRJIg8yNzNFMDk1RjVB\n" +
|
886
|
-
# "BzsGVDobQHVuY29udmVydGFibGVfdG9fYnNvblRJIgl0YWdzBjsGVFsASSIL\n" +
|
887
|
-
# "YWN0aXZlBjsGVFRJIhhzdWJzY3JpYmVkX3VzZXJfaWRzBjsGVFsASSIMZGV0\n" +
|
888
|
-
# "YWlscwY7BlRDOwB7BkkiB2VuBjsGVEM7AHsASSIMZmlsdGVycwY7BlRDOwB7\n" +
|
889
|
-
# "BkkiB2VuBjsGVEM7AHsASSINdGVtcGxhdGUGOwZUSSIMZ2VuZXJpYwY7BlRJ\n" +
|
890
|
-
# "IhBwdXJjaGFzYWJsZQY7BlRUSSIJbmFtZQY7BlRDOwB7BkkiB2VuBjsGVEki\n" +
|
891
|
-
# "FEVzY2FwZSB0aGUgUm9vbQY7BlRJIgxkaWdpdGFsBjsGVEZJIglzbHVnBjsG\n" +
|
892
|
-
# "VEkiFGVzY2FwZS10aGUtcm9vbQY7BlRJIg91cGRhdGVkX2F0BjsGVEl1OglU\n" +
|
893
|
-
# "aW1lDfJeHcBolXe5BjoJem9uZUkiCFVUQwY7BkZJIg9jcmVhdGVkX2F0BjsG\n" +
|
894
|
-
# "VEl1OwgN8l4dwGiVd7kGOwlJIghVVEMGOwZG\n"},
|
895
|
-
# "sort"=>[6.044283, 1503513983497]}]},
|
896
|
-
# "aggregations"=> # ...}
|
897
|
-
```
|
898
|
-
|
899
|
-
The `#results` method returns the "loaded" results, which de-serializes each result into a Mogoid model. These results are suitable for display in the UI.
|
900
|
-
|
901
|
-
```ruby
|
902
|
-
product_admin_search_query.results.class
|
903
|
-
# => Workarea::PagedArray
|
904
|
-
|
905
|
-
product_admin_search_query.results.to_a.map(&:class)
|
906
|
-
# => [Workarea::Catalog::Product]
|
907
|
-
|
908
|
-
product_admin_search_query.results.first.id
|
909
|
-
# => "273E095F5A"
|
910
|
-
|
911
|
-
product_admin_search_query.results.first.name
|
912
|
-
# => "Escape the Room"
|
913
|
-
```
|
914
|
-
|
915
|
-
### Product Results
|
916
|
-
|
917
|
-
Search queries that return products, such as `ProductSearch`, `CategoryBrowse`, and `RelatedProducts` include the `LoadProductResults` module, which changes the behavior of `results`.
|
918
|
-
|
919
|
-
For each result, these queries return a hash of objects rather than a single object.
|
920
|
-
|
921
|
-
```ruby
|
922
|
-
product_search = Workarea::Search::ProductSearch.new(q: 'marble')
|
923
|
-
|
924
|
-
product_search.results.class
|
925
|
-
# => Workarea::PagedArray
|
926
|
-
|
927
|
-
product_search.results.to_a.map(&:class)
|
928
|
-
# => [Hash, Hash, Hash, Hash, Hash, Hash, Hash, Hash, Hash]
|
929
|
-
```
|
930
|
-
|
931
|
-
The following examples show the keys in this hash and the type of each value.
|
932
|
-
|
933
|
-
```ruby
|
934
|
-
product_search.results.first.keys
|
935
|
-
# => [:id, :catalog_id, :model, :option, :pricing, :inventory]
|
936
|
-
|
937
|
-
pp Hash[product_search.results.first.map { |k,v| [k, v.class] }]
|
938
|
-
# {:id=>String,
|
939
|
-
# :catalog_id=>String,
|
940
|
-
# :model=>Workarea::Catalog::Product,
|
941
|
-
# :option=>NilClass,
|
942
|
-
# :pricing=>Workarea::Pricing::Collection,
|
943
|
-
# :inventory=>Workarea::Inventory::Collection}
|
944
|
-
|
945
|
-
product_search.results.first[:catalog_id]
|
946
|
-
# => "29C9ECAAF2"
|
947
|
-
|
948
|
-
product_search.results.first[:model].name
|
949
|
-
# => "Practical Marble Clock"
|
950
|
-
```
|
951
|
-
|
952
|
-
### Composing the Search Request Body
|
953
|
-
|
954
|
-
As mentioned above, search queries perform an Elasticsearch request body search. These search requests use a request body constructed from the [Elasticsearch query DSL](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/query-dsl.html).
|
955
|
-
|
956
|
-
Search queries provide a Ruby interface for composing these request bodies. The `body` method is responsible for returning a hash which represents the request body. Many other methods are potentially used to compose this final hash. Below is the default implementation of `Workarea::Search::Query#body`.
|
957
|
-
|
958
|
-
```ruby
|
959
|
-
module Workarea
|
960
|
-
module Search
|
961
|
-
module Query
|
962
|
-
# ...
|
963
|
-
|
964
|
-
def body
|
965
|
-
{
|
966
|
-
query: query,
|
967
|
-
post_filter: post_filter,
|
968
|
-
aggs: aggregations
|
969
|
-
}
|
970
|
-
.merge(additional_options)
|
971
|
-
.delete_if { |_, v| v.blank? }
|
972
|
-
end
|
973
|
-
|
974
|
-
# ...
|
975
|
-
end
|
976
|
-
end
|
977
|
-
end
|
978
|
-
```
|
979
|
-
|
980
|
-
Each search query extends or implements the methods necessary to produce the desired request body. As you can see above, the methods `query`, `post_filter`, and `aggregations` contribute directly to the body. The `additional_options` method, calls a method for each search query option included in `Workarea.config.search_query_options`, allowing for configuration of the query builder.
|
981
|
-
|
982
|
-
```ruby
|
983
|
-
Workarea.config.search_query_options
|
984
|
-
# => ["sort", "size", "from", "suggest"]
|
985
|
-
```
|
986
|
-
|
987
|
-
Many search queries include some of the following modules, which help to build up the desired request body.
|
988
|
-
|
989
|
-
- `Workarea::Search::CategorizationFiltering`
|
990
|
-
- `Workarea::Search::Facets`
|
991
|
-
- `Workarea::Search::Pagination`
|
992
|
-
- `Workarea::Search::LoadProductResults`
|
993
|
-
- `Workarea::Search::ProductDisplayRules`
|
994
|
-
- `Workarea::Search::QuerySuggestions`
|
995
|
-
- `Workarea::Search::ProductRules`
|
996
|
-
- `Workarea::Search::AdminIndexSearch`
|
997
|
-
- `Workarea::Search::AdminSorting`
|
998
|
-
|
999
|
-
## Notes
|
1000
|
-
|
1001
|
-
[1] Documents of type _category_ are stored in the same indexes as documents of type _storefront_.
|
1002
|
-
|
1003
|
-
[2] The _storefront_ key declares mappings for the _storefront_ **and** _category_ types, since both document types are stored in the same indexes.
|
1004
|
-
|
1005
|
-
[3] `Workarea::Search::Help` has no descendants and is used directly to save and destroy documents.
|