4

我试图在默认的 SearchResult 页面中显示某些 DataObjects(新闻)。所以结果应该显示正常的页面和新闻。

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

我发现了这一点,但显然现在禁用了搜索: https ://github.com/arambalakjian/DataObjects-as-Pages

谢谢和问候,弗洛里安

4

3 回答 3

8

我通常会在启用FulltextSearchable. 所以_config.php我会

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

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

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

然后在我的PageController我有我的自定义searchForm结果功能。

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

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'));
}

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

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

于 2013-01-23T21:28:02.953 回答
2

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

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

于 2013-11-29T01:13:39.063 回答
1

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

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

于 2013-01-23T21:26:36.507 回答