【问题标题】:silverstripe dataobject searchablesilverstripe 数据对象可搜索
【发布时间】:2013-01-07 04:16:36
【问题描述】:

我正在尝试在默认搜索结果页面中显示某些数据对象(新闻)。所以结果应该显示正常的页面和新闻。

在 Silverstripe 3 中是否有简单的方法来实现这一点? 还是建议将其完全自定义编码-我的意思是处理搜索请求并创建结果列表的自定义控制器/操作,然后我将其显示在自定义模板中?

我找到了这个,但显然搜索现在被禁用: https://github.com/arambalakjian/DataObjects-as-Pages

谢谢和问候, 弗洛里安

【问题讨论】:

    标签: content-management-system silverstripe


    【解决方案1】:

    我已将 @colymba 的解决方案改编成 silverstripe 模块:https://github.com/burnbright/silverstripe-pagesearch

    它允许在 url 中设置页面类型。

    【讨论】:

      【解决方案2】:

      我通常会在启用FulltextSearchable 后一起自定义搜索功能。所以在_config.php 我会有

      FulltextSearchable::enable();
      Object::add_extension('NewsStory', "FulltextSearchable('Name,Content')");
      

      NameContent 替换为您希望可搜索的任何 DBField。每个可搜索的DataObject 在他们的类中都有这个来启用搜索索引(很确定这需要在启用扩展之前添加并运行 dev/build,并且只适用于 MySQL DB)。

      static $create_table_options = array(
        'MySQLDatabase' => 'ENGINE=MyISAM'
      );
      

      然后在我的PageController 我有我的自定义searchFormresults 函数。

      这是返回搜索表单的search 函数,在模板中使用$search 调用:

      public function search()
      {       
        if($this->request && $this->request->requestVar('Search')) {
          $searchText = $this->request->requestVar('Search');
        }else{
          $searchText = 'Search';
        }
      
        $f = new TextField('Search', false, $searchText);
      
        $fields = new FieldList(
          $f
        );
        $actions = new FieldList(
          new FormAction('results', 'Go')
        );
        $form = new Form(
          $this,
          'search',
          $fields,
          $actions
        );
        //$form->disableSecurityToken();
        $form->setFormMethod('GET');
        $form->setTemplate('SearchForm');
      
        return $form;
      }
      

      这里还有用于处理查询的自定义 results 函数...

      function results($data, $form, $request)
      {   
        $keyword = trim($request->requestVar('Search'));
        $keyword = Convert::raw2sql($keyword);
        $keywordHTML = htmlentities($keyword, ENT_NOQUOTES, 'UTF-8');    
      
        $pages = new ArrayList();
        $news = new ArrayList();
      
        $mode = ' IN BOOLEAN MODE';
        //$mode = ' WITH QUERY EXPANSION';
        //$mode = '';
      
        $siteTreeClasses = array('Page');
        $siteTreeMatch = "MATCH( Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords ) AGAINST ('$keyword'$mode)
                        + MATCH( Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords ) AGAINST ('$keywordHTML'$mode)";
      
        $newsItemMatch = "MATCH( Name, Content ) AGAINST ('$keyword'$mode)
                        + MATCH( Name, Content ) AGAINST ('$keywordHTML'$mode)";
      
        //Standard pages
        foreach ( $siteTreeClasses as $c )
        {
          $query = DataList::create($c)
            ->where($siteTreeMatch);
          $query = $query->dataQuery()->query();
          $query->addSelect(array('Relevance' => $siteTreeMatch));
      
          $records = DB::query($query->sql());
          $objects = array();
          foreach( $records as $record )
          {
            if ( in_array($record['ClassName'], $siteTreeClasses) )
              $objects[] = new $record['ClassName']($record);
          }
          $pages->merge($objects);
        }
      
      
        //news
        $query = DataList::create('NewsStory')->where($newsItemMatch);
        $query = $query->dataQuery()->query();
        $query->addSelect(array('Relevance' => $newsItemMatch));
      
        $records = DB::query($query->sql());
        $objects = array();
        foreach( $records as $record ) $objects[] = new $record['ClassName']($record);
        $news->merge($objects);
      
      
        //sorting results
        $pages->sort(array(
          'Relevance' => 'DESC',
          'Title' => 'ASC'
        ));      
        $news->sort(array(
          'Relevance' => 'DESC',
          'Date' => 'DESC'
        ));
      
        //output
        $data = array(
          'Pages' => $pages,
          'News' => $news,
          'Query' => $keyword
        ); 
        return $this->customise($data)->renderWith(array('Search','Page'));
      }
      

      我在$siteTreeClasses 数组中添加了我想要搜索的所有Page 类,并在$siteTreeClasses 数组中扩展了SiteTree,并且几乎可以复制News 部分对于任何其他DataObject我需要搜索。

      我并不是说这是最好的解决方案,这肯定可以改进,但它对我有用,这可能是一个很好的说明。

      【讨论】:

      • 嘿!我设法或多或少地按照你的方式做到了。我从 MySQLDatabase.php 中取出了整个 searchEngine 函数并对其进行了调整:gist.github.com/4660526#file-page-php
      • 您如何访问搜索结果模板中的结果?
      • 在这种情况下,您可以在模板中使用$Pages$News 访问结果,并使用<% loop XXX %> 迭代每个结果集。
      • 哦,是的。对不起,我现在明白了。在 $data 中设置。太棒了,这是修补我的搜索页面的一个很好的起点。谢谢科林巴!
      【解决方案3】:

      您需要大量覆盖SearchForm->getResults()。 它使用Database->searchEngine(),但这些是针对SiteTreePage 类量身定制的。

      “正确”的解决方案是将数据输入到 Solr 或 Sphinx 等搜索引擎中。 为此,我们有 SS3 兼容的“全文搜索”模块: https://github.com/silverstripe-labs/silverstripe-fulltextsearch 这将需要一些前期设置,并且只有当您可以自己托管 Solr 或准备为 SaaS 提供商付费时才可行。但是,一旦您开始运行它,可能性就无穷无尽,它是一个很棒的工具!

      【讨论】:

      • 嘿 ingo,我正在尝试覆盖核心类 SearchForm 和 MySQLDatabase。我创建了类 CustomSearchForm 和 CustomMySQLDatabase 来扩展这些核心类。然后我在配置中添加了这些行:Object::useCustomClass('SearchForm', 'CustomSearchForm', true); Object::useCustomClass('MySQLDatabase', 'CustomMySQLDatabase', true);,但 silverstripe 仍然使用核心类。怎么会?谢谢
      • 英戈。是否有改进内置搜索的计划?考虑到 shinx / solr 是 silverstripe “正确” 的搜索方式,我们中的很多人都落后于他们的客户,他们离拥有不受管理的私人服务器很远。
      猜你喜欢
      • 1970-01-01
      • 2016-06-28
      • 1970-01-01
      • 1970-01-01
      • 2015-11-10
      • 1970-01-01
      • 2017-07-10
      • 1970-01-01
      • 2018-04-06
      相关资源
      最近更新 更多