使用 UI 中的搜索

可视化组件

搜索扩展组件提供两个 UI 组件:SearchFieldFullTextFilter

在为项目添加了搜索扩展组件后,这两个 UI 组件可以通过 Studio 视图设计器Add Component 工具箱添加。

如果不使用视图设计器,也可以在视图的 XML 中手动声明 search 命名空间:

<view xmlns="http://jmix.io/schema/flowui/view"
      xmlns:search="http://jmix.io/schema/search/ui"
      title="msg://searchView.title">

SearchField

SearchField 组件提供一个文本框和一个执行搜索的按钮。

视图中使用 SearchField 的示例:

<view xmlns="http://jmix.io/schema/flowui/view"
      xmlns:search="http://jmix.io/schema/search/ui"
      title="msg://searchView.title">
    <layout>
        <search:searchField id="searchField"/>
    </layout>
</view>

SearchField 组件的属性:

  • searchStrategy - 定义使用的搜索策略。如未定义,则使用默认策略。

  • entities - 设置在指定的实体内进行搜索。多个实体可用逗号分隔:

    <search:searchField id="searchField"
                        entities="Customer, Order_"/>

默认情况下,searchField 打开内置的 SearchResultsView 视图。该视图会对搜索引擎进行查询,并根据 searchField 配置的 openMode 的不同在导航页面或对话框内展示搜索结果。

如需自定义该行为,可以按如下设置 SearchCompletedHandler

@Autowired
private DialogWindows dialogWindows;
@ViewComponent
private SearchField searchField;

@Install(to = "searchField", subject = "searchCompletedHandler")
private void searchFieldSearchCompletedHandler(
        final SearchField.SearchCompletedEvent event) {
    SearchResult searchResult = event.getSearchResult();
    DialogWindow<SearchResultsView> searchResultsDialog =
            dialogWindows.view(UiComponentUtils.getView(this),
                            SearchResultsView.class)
                    .build();
    SearchResultsView view = searchResultsDialog.getView();
    view.initView(new SearchFieldContext(searchField));
    searchResultsDialog.open();
}

另外,也可以使用组件的 setSearchCompletedHandler() 方法设置。

FullTextFilter

FullTextFilter 组件的功能与 propertyFilter 属性过滤器 类似。

视图中使用 fullTextFilter 的示例:

<data>
    <collection id="ordersDc"
                class="com.company.demo.entity.Order">
        <loader id="ordersDl"
                readOnly="true">
            <query>
                <![CDATA[select e from Order_ e]]>
            </query>
        </loader>
        <fetchPlan extends="_base">
            <property name="customer"
                      fetchPlan="_base"/>
        </fetchPlan>
    </collection>
</data>
<layout>
    <search:fullTextFilter dataLoader="ordersDl"
                           autoApply="true"/>
    <dataGrid id="ordersDataGrid"
              width="100%"
              dataContainer="ordersDc">
        <columns>
            <column property="number"/>
            <column property="date"/>
            <column property="amount"/>
            <column property="product"/>
        </columns>
    </dataGrid>
</layout>

FullTextFilter 组件的属性:

  • dataLoader - 设置需要过滤的 DataLoader

  • searchStrategy - 搜索策略。如未定义,则使用默认策略。

  • autoApply - 如果设置为 true,则在组件值发生变更时,组件自动对 DataLoader 使用过滤。

FullTextFilter 的工作流程:首先使用全文搜索找到实体的 id,然后在数据加载器中添加带这些 ID 的过滤条件。接下来,关联至该加载器的 DataGrid 只展示符合全文搜索条件的记录,如果 DataGrid 组件有其他过滤器,也会生效。

搜索策略

搜索策略定义如何处理搜索词。基本上是使用一些查询语句配置搜索请求。

SearchFieldFullTextFilter 组件支持下列内置的搜索策略:

  • anyTermAnyField - 文档的任何索引字段匹配至少一个输入词。

  • allTermsAnyField - 文档的任何索引字段以任何顺序匹配上所有的输入词。这是默认策略。

  • allTermsSingleField - 文档至少有一个字段包含任意顺序的所有输入词。

  • phrase - 文档至少有一个字段包含输入顺序的所有输入词。

可以使用 strategy 属性设置合适的搜索策略,示例:

<search:fullTextFilter dataLoader="ordersDl"
                       autoApply="true"
                       searchStrategy="anyTermAnyField"/>

如需覆盖默认策略,在 application.properties 文件添加下列应用程序属性:

jmix.search.default-search-strategy = allTermsSingleField

自定义搜索策略

另外,也可以创建自己的搜索策略。为此,首先创建一个实现下列接口之一的 Spring bean:

  • OpenSearchSearchStrategy - 如果使用 OpenSearch。

  • ElasticsearchSearchStrategy - 如果使用 Elasticsearch。

然后需要实现两个方法:

  • String getName() - 返回策略的唯一名称。

  • void configureRequest(SearchRequest.Builder requestBuilder, SearchContext searchContext) - 根据需要使用传入的 builder 配置所需的搜索请求。

@Component
public class CustomOpenSearchSearchStrategy implements OpenSearchSearchStrategy {

    @Override
    public String getName() {
        return "CustomStrategy";
    }

    @Override
    public void configureRequest(SearchRequest.Builder requestBuilder, SearchContext searchContext) {
        //configure your request
        requestBuilder.query(queryBuilder ->
                queryBuilder.multiMatch(multiMatchQueryBuilder ->
                        multiMatchQueryBuilder.fields("*")
                                .query(searchContext.getSearchText())
                )
        );
    }
}

然后,可以在 SearchFieldFullTextFilter 组件使用策略名称设置策略。

过滤器组件中的全文搜索条件

当项目中添加了搜索扩展组件后,GenericFilter 组件的 Add condition(添加条件) 弹窗会出现一个新的条件:

add condition

Full-text filter condition editor(全文过滤条件编辑) 对话框中,你可以为全文过滤器设置标题并选择一个搜索策略。如果未设置,则使用默认策略。

condition editor

与过滤器关联的列表组件中的记录会基于全文搜索结果过滤。

视图中使用搜索 API

视图控制器中可以使用搜索 API,示例:

@Autowired
private EntitySearcher entitySearcher;

@Autowired
private SearchResultProcessor searchResultProcessor;

@Subscribe(id = "searchBtn", subject = "clickListener") (1)
public void onSearchBtnClick(final ClickEvent<JmixButton> event) {
    SearchContext searchContext = new SearchContext("silver") (2)
            .setSize(20) (3)
            .setEntities("Order_"); (4)
    SearchResult searchResult = entitySearcher.search(searchContext); (5)
    Collection<Object> instances =
            searchResultProcessor.loadEntityInstances(searchResult); (6)
    // ...
}
1 点击按钮时,从视图控制器调用 API。
2 定义搜索字符串,这一步是必须的,会搜索所有的索引字段,并找出其中是否包含 "silver"
3 设置返回结果集中包含的记录数量。默认值为 10
4 设置搜索的实体。默认会搜素全部的索引实体。
5 使用 EntitySearcher 服务启动搜索。
6 使用 SearchResultProcessor 从搜索结果中获取实体。