i-lateral / silverstripe-searchable

Adds to default SilverStripe search with configurable FullTextSearch, custom results controller and allowing adding custom data objects and custom fields for searching via config
BSD 3-Clause "New" or "Revised" License
13 stars 12 forks source link

Searching subclasses of Page #1

Open briceburg opened 9 years ago

briceburg commented 9 years ago

Is it possible to search objects that extend Page? For instance; I have a type, Article that extends Page and provides the following extra fields; Author and Summary. SilverStripe will create a database table named Article that containts the above fields as columns, but borrows upon the SiteTree table for the Content and Title field.

I want to be able to search by Author, Summary text, Content text, and Title.. and add the following to _config;

Searchable::add('Article',array('Author','Summary','Content','Title'),'News Articles');

This results in:

[User Error] Couldn't run query: ALTER TABLE "Article" ADD fulltext "SearchFields" ("Author","Summary","Content","Title") Key column 'Content' doesn't exist in table

As those [Content, Title] fields don't exist on the Article table.

Does the module support this scenario?

Many thanks for any ideas.

~ Brice

mlewis-everley commented 9 years ago

I have encountered this issue as well, it is a scenario I would definitly like to support and I thought Silverstripe would automatically perform a join onto parent objects when filtering.

Apparently however this is not the case (or my code is incorrect in some way), so I am trying to work out how to get this working and any help would be greatly appreciated :-).

briceburg commented 9 years ago

I'm in the midst of coding my own search routine. I handle therelationships by checking for the presence of "." in the search field, and only add fulltext indexes on fields that belong to the Class table. Here's a quick preview;

$searchClasses = array(
    'SiteTree' => array('Title','Content'),
    'Article' => array('Author','Summary','SiteTree.Title','SiteTree.Content'),
    'Attorney' => array('Email','SideContent','DirectPhone','DirectFax','SiteTree.Content','SiteTree.Title'),
    'Practice' => array('SiteTree.Title','SiteTree.Content'),
    'Region' => array('Summary','SiteTree.Title','SiteTree.Content'),
);

SearchableExtension::enable($searchClasses);
class SearchableExtension extends DataExtension
{

    public static $searchClasses = array();

    public static function enable($searchClasses = array())
    {
        foreach ($searchClasses as $class => $fields) {

            $tableFields = array_filter($fields,
                function ($var)
                {
                    return (strpos($var, '.') === false);
                });

            if (! empty($tableFields)) {
                //@todo ONLY if mysql version < 5.6
                Config::inst()->update($class, 'create_table_options',
                    array(
                        'MySQLDatabase' => 'ENGINE=MyISAM'
                    ));

                $tableFieldsStr = implode(',',
                    array_map(
                        function ($var)
                        {
                            return sprintf('"%s"', $var);
                        }, $tableFields));

                $class::add_extension("FulltextSearchable('$tableFieldsStr')");
            }
        }

        self::$searchClasses = $searchClasses;
    }

    public static function get_extra_config($class, $extensionClass, $args)
    {
        return array(
            'indexes' => array(
                'SearchFields' => array(
                    'type' => 'fulltext',
                    'name' => 'SearchFields',
                    'value' => $args[0]
                )
            )
        );
    }
}
mlewis-everley commented 9 years ago

Ok, I think I can see what you are doing. It would be be a little less reliant on configuration if the enable method tried to automatically detect if the class provided is an extension and if the fields to search exist on that class or the parent...

Not sure how to though, will have to have a ponder...