eZ Community » Forums » Extensions » eZ Find » Problem with not main nodes in...
expandshrink

Problem with not main nodes in SearchSubTreeArray

Problem with not main nodes in SearchSubTreeArray

Friday 29 October 2010 1:49:44 pm - 9 replies

Hi everyone!

Today i discoverd a troubles with searching non main nodes. I`ll try to explaine the problem:

We have object O1 (name: "test"blunk.gif Emoticon, with multiple locations:

  • N1 (main, node_id:101, path:1/2/60/101)
  • N2 (node_id:102, path: 1/2/62/102)
  • N3 (node_id:103, path: 1/2/63/103)

I`m doing the next:

$solrSearch   = new eZSolr();
$searchResult = $solrSearch->search(
    'test',
    array(
        'SearchSubTreeArray' => array( 62 ),
        'SpellCheck' => array( true ),
        'SearchType' => array( 'fulltext' ),
        'SearchLimit' => 10,
        'SearchOffset' => 0
    )
)

$searchResult['SearchResult'] should contain the eZFindResultNode object with node_id = 102. But it contains eZFindResultNode object with node_id = 101. Its because $searchResult['SearchResult'] allways contains just main nodes.

In my case i didn`t used score_percent and highlight attributes, so i fixed it the next way:

foreach( $searchResult['SearchResult'] as $key => $node ) {
    if( in_array( $parentNodeID, $node->attribute( 'path_array' ) ) === false ) {
        $locations = $node->attribute( 'object' )->attribute( 'assigned_nodes' );
        foreach( $locations as $locationNode ) {
            if( in_array( $parentNodeID, $locationNode->attribute( 'path_array' ) ) === true ) {
                $nodeRow  = eZContentObjectTreeNode::fetch( $locationNode->attribute( 'node_id' ), false, false );
                $findNode = new eZFindResultNode( $nodeRow );
                $findNode->setContentObject( new eZContentObject( $nodeRow ) );
                $findNode->setAttribute( 'name', $locationNode->attribute( 'name' ) );
                $findNode->setAttribute( 'published', $locationNode->attribute( 'published' ) );
                $findNode->setAttribute( 'global_url_alias', $locationNode->attribute( 'url_alias' ) );
                $findNode->setAttribute( 'language_code', $locationNode->attribute( 'object' )->attribute( 'current_language' ) );
                $findNode->setAttribute( 'is_local_installation', true );
 
                $searchResult['SearchResult'][ $key ] = $findNode;
                break;
            }
        }
    }
}

But i think it will be great if this bug will be fixed in eZ Find, and $searchResult['SearchResult'] will contain no only main nodes happy.gif Emoticon

Modified on Friday 29 October 2010 3:24:16 pm by Serhey Dolgushev

Friday 29 October 2010 4:02:29 pm

Hi Serhey,

Which version of eZ Find are you using ?

Cheers,

Saturday 30 October 2010 12:58:17 pm

Its 2.2-0

Sunday 31 October 2010 9:23:33 pm

Hi Serhey

Can you file a bug report/enhancement request referrring to this thread? Your use case is not the only one, so some flexibility on this should be introduced ... sometimes, the main node is what one really wants.

Regards

Paul

Thursday 04 November 2010 11:58:01 pm

Hi Paul. I did it: http://issues.ez.no/IssueView.php?Id=17576&activeItem=3

Saturday 06 November 2010 11:08:21 am

Hi Paul. I did it: http://issues.ez.no/IssueView.php?Id=17576&activeItem=3

Thanks Serhey!

Tuesday 10 April 2012 12:25:21 pm

Hmm, ok now we show other locations but what should I do if I want to only get main nodes for a ezfind fetch?

I'm looking for a "main_node_only" parameter but I cannot find any.

Monday 04 June 2012 9:21:28 am

Hi ,

I have same problem with ezfind2.2.

We have object O1 (name: "new", with multiple locations):

N1 (main, node_id:99064, path:/1/2/59/99064)
N2 (node_id:28456, path: /1/2/15631/28456)
N3 (node_id:4911, path: /1/2/15631/4911)

ezfind fetch query is as below:

{def $search=fetch( ezfind,search,
                            hash( 'query', $key,
                                   subtree_array, array( 28456),
                                  'class_id', array('article'),                     
                                  'sort_by', hash( 'article/title', 'asc' ),
                                  'facet', $defaultSearchFacets,                                 
                                  'spell_check', array( true() ),
                                  'offset', $page,
                                  'limit',20
                                 ))}

$searchResult['SearchResult'] should contain the eZFindResultNode object with node_id = 28456. But it contains eZFindResultNode object with node_id = 99064. Its because $searchResult['SearchResult'] allways contains just main nodes.

I have used below thread to resolve the issue:

http://issues.ez.no/IssueView.php?Id=17576&activeItem=3

But when i write

subtree_array, array(ezhttp('SubTree', 'get'))

in fetch function,fetch function didnt return anything.

In above subtree_array parameter how we can pass nodeid from which only we need search result?

Please help me to solve this issue.

Thanks in advance.

Monday 04 June 2012 12:03:04 pm

Hi All,

I have got solution.

Please modify ezsolr.php file on the below location.

/ezfind/search/plugins/ezsolr/ezsolr.php.

Please see the below updated file. Below file is useful for ezfind version 2.2.

If anyone has same issue can use below file.

 <?php
//
// ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
// SOFTWARE NAME: eZ Find
// SOFTWARE RELEASE: 2.2-0
// COPYRIGHT NOTICE: Copyright (C) 1999-2010 eZ Systems AS
// EXTENDED COPYRIGHT NOTICE :
//      Part of this class was inspired from the following contributors' work :
//      * Kristof Coomans <kristof[dot]coomans[at]telenet[dot]be>
//      * Paul Borgermans <pb[at]ez[dot]no> ( when not employed yet by eZ Systems )
//      * SCK-CEN as a legal entity <http://www.sckcen.be/>
// SOFTWARE LICENSE: GNU General Public License v2.0
// NOTICE: >
//   This program is free software; you can redistribute it and/or
//   modify it under the terms of version 2.0  of the GNU General
//   Public License as published by the Free Software Foundation.
//
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.
//
//   You should have received a copy of version 2.0 of the GNU General
//   Public License along with this program; if not, write to the Free
//   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//   MA 02110-1301, USA.
//
//
// ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
//



/**
 * Solr search plugin for eZ publish
 */
class eZSolr
{
    /**
     * Constructor
     */
    function __construct()
    {
        eZDebug::createAccumulatorGroup( 'solr', 'Solr search plugin' );
        $this->SolrINI = eZINI::instance( 'solr.ini' );
        $this->FindINI = eZINI::instance( 'ezfind.ini' );
        $this->SiteINI = eZINI::instance( 'site.ini' );
        //$this->Solr = self::solrBaseFactory();
        $this->UseMultiLanguageCores = false;
        if ( $this->FindINI->variable( 'LanguageSearch', 'MultiCore' ) == 'enabled' )
        {
            $this->UseMultiLanguageCores = true;
        }
        $this->initLanguageShards();
    }

    /**
     * Get list of meta attributes and their field types.
     *
     * @return array List of meta attributes and the field types.
     */
    static function metaAttributes()
    {
        return array(
            'id' => 'sint',
            'class_name' => 'string',
            'section_id' => 'sint',
            'owner_id' => 'sint',
            'contentclass_id' => 'sint',
            'current_version' => 'sint',
            'remote_id' => 'string',
            'class_identifier' => 'string',
            'main_node_id' => 'sint',
            'modified' => 'date',
            'published' => 'date',
            'main_parent_node_id' => 'sint' );
    }

    /**
     * Fetches the meta attributes for a given content object
     * and fill the structure described below.
     *
     * @param eZContentObject $object
     * @return array
     * <code>
     *    array(
     *          array( 'name'     => 'id'
     *                 'value'     => 82
     *                 'fieldType' => 'sint' ),
     *                 ...
     *         )
     * </code>
     *
     * @see eZSolr::metaAttributes()
     */
    public static function getMetaAttributesForObject( eZContentObject $object )
    {
        $metaAttributeValues = array();
        foreach( self::metaAttributes() as $attributeName => $fieldType )
        {
            $metaAttributeValues[] = array( 'name' => $attributeName,
                                            'value' => $object->attribute( $attributeName ),
                                            'fieldType' => $fieldType );
        }
        return $metaAttributeValues;
    }

    /**
     * Get list of Node attributes and their field types
     *
     * @return array List of node attributes and field types.
     */
    static function nodeAttributes()
    {
        return array( 'node_id' => 'sint',
                      'path_string' => 'string',
                      'url_alias' => 'string',
                      'is_hidden' => 'boolean',
                      'is_invisible' => 'boolean',
                      'sort_field' => 'string',
                      'sort_order' => 'string' );
    }

    /**
     * Get meta attribute Solr document field type
     *
     * @param  string name Meta attribute name
     * @param  string context search, facet, filter, sort
     *
     * @return string Solr document field type. Null if meta attribute type does not exists.
     */
    static function getMetaAttributeType( $name, $context = 'search' )
    {
       

        $attributeList = array ('search' => array_merge( array( 'guid' => 'string',
                                             'installation_id' => 'string',
                                             'installation_url' => 'string',
                                             'name' => 'text',
                                             'anon_access' => 'boolean',
                                             'language_code' => 'string',
                                             'available_language_codes' => 'string',
                                             'main_url_alias' => 'string',
                                             'owner_name' => 'text',
                                             'owner_group_id' => 'sint',
                                             'path' => 'sint',
                                             'object_states' => 'string'),
                                      self::metaAttributes(),
                                      self::nodeAttributes() ),
                                'facet' =>  array( 
                                             'owner_name' => 'string'),
                                'filter' => array(),
                                'sort' => array() );
        if ( ! empty( $attributeList[$context][$name] ) )
        {
            return $attributeList[$context][$name];
        }
        elseif ( ! empty( $attributeList['search'][$name] ) )
        {
            return $attributeList['search'][$name];
        }
        else
        {
            return null;
        }
        //return $attributeList[$name];
    }

    /**
     * Get solr field name, from base name. The base name may either be a
     * meta-data name, or an eZ Publish content class attribute, specified by
     * <class identifier>/<attribute identifier>[/<option>]
     *
     * @param string $baseName Base field name.
     * @param boolean $includingClassID conditions the structure of the answer. See return value explanation.
     * @param $context is introduced in ez find 2.2 to allow for more optimal sorting, faceting, filtering
     *
     * @return mixed Internal base name. Returns null if no valid base name was provided.
     *               If $includingClassID is true, an associative array will be returned, as shown below :
     *               <code>
     *               array( 'fieldName'      => 'attr_title_t',
     *                      'contentClassId' => 16 );
     *               </code>
     */
    static function getFieldName( $baseName, $includingClassID = false, $context = 'search' )
    {
        // If the base name is a meta field, get the correct field name.
        if ( eZSolr::hasMetaAttributeType( $baseName, $context ) )
        {
            return eZSolr::getMetaFieldName( $baseName, $context );
        }
        else
        {
            // Get class and attribute identifiers + optional option.
            $subattribute = null;
            $fieldDef = explode( '/', $baseName );
            // Check if content class attribute ID is provided.
            if ( is_numeric( $fieldDef[0] ) )
            {
                if ( count( $fieldDef ) == 1 )
                {
                    $contectClassAttributeID = $fieldDef[0];
                }
                else if ( count( $fieldDef ) == 2 )
                {
                    list( $contectClassAttributeID, $subattribute ) = $fieldDef;
                }
            }
            else
            {
                switch( count( $fieldDef ) )
                {
                    case 1:
                    {
                        // Return fieldname as is.
                        return $baseName;
                    } break;

                    case 2:
                    {
                        // Field def contains class indentifier and class attribute identifier.
                        list( $classIdentifier, $attributeIdentifier ) = $fieldDef;
                    } break;

                    case 3:
                    {
                        // Field def contains class indentifier, class attribute identifier and optional specification.
                        list( $classIdentifier, $attributeIdentifier, $subattribute ) = $fieldDef;
                    } break;
                }
                $contectClassAttributeID = eZContentObjectTreeNode::classAttributeIDByIdentifier( $classIdentifier . '/' . $attributeIdentifier );
            }
            if ( !$contectClassAttributeID )
            {
                eZDebug::writeNotice( 'Could not get content class from base name: ' . $baseName,
                                      'eZSolr::getFieldName()' );
                return null;
            }
            $contectClassAttribute = eZContentClassAttribute::fetch( $contectClassAttributeID );
            $fieldName = ezfSolrDocumentFieldBase::getFieldName( $contectClassAttribute, $subattribute, $context );

            if ( $includingClassID )
            {
                return array( 'fieldName'      => $fieldName,
                              'contentClassId' => $contectClassAttribute->attribute( 'contentclass_id' ) );
            }
            else
                return $fieldName;
        }
    }

    /**
     * Check if eZSolr has meta attribute type.
     *
     * @param string Meta attribute name
     *
     * @return string Solr document field type
     */
    static function hasMetaAttributeType( $name, $context )
    {
        return self::getMetaAttributeType( $name, $context ) !== null;
    }

    /**
     * @todo: cleanup the recursive lookup in ezfSolrDocumentFieldBase::generateMetaFieldName, it is only overhead
     *
     * Get meta attribute field name
     *
     * @param string Meta attribute field name ( base )
     *
     * @return string Solr doc field name
     */
    static function getMetaFieldName( $baseName, $context = 'search' )
    {
        /*
        return self::$SolrDocumentFieldName->lookupSchemaName( 'meta_' . $baseName,
                                                               eZSolr::getMetaAttributeType( $baseName ) );
        */
        return ezfSolrDocumentFieldBase::generateMetaFieldName( $baseName, $context );
    }

    /**
     * Get attribute field name base. Extracts the base name from
     * attribute field name
     *
     * @param string Full field name, example: meta_owner_id_s
     *
     * @return string Base name, example: owner_id . Returns null if no matches are found.
     */
    static function getFieldBaseName( $fieldName )
    {
        $matches = array();
        if ( preg_match( '/w*_(.*)_w*/', $fieldName, $matches ) )
        {
            return $matches[1];
        }

        return null;
    }

    /**
     * @since eZ Find 2.1
     *
     * Returns the relative URL Alias for a given search result,
     * depending on whether a subtree filter was applied or not.
     *
     * @param array $doc The search result, directly received from Solr.
     * @return string The URL Alias corresponding the the search result
     */
    protected function getUrlAlias( $doc )
    {
        if ( isset( $this->postSearchProcessingData['subtree_array'] ) and !empty( $this->postSearchProcessingData['subtree_array'] ) )
        {
            foreach ( $this->postSearchProcessingData['subtree_array'] as $subtree )
            {
                foreach ( $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'path_string' )] as $pathString )
                {
                    if ( substr_count( $pathString, '/' . $subtree . '/' ) > 0 )
                    {
                        $nodeArray = explode( '/', rtrim( $pathString, '/' ));
                        $nodeID = array_pop( $nodeArray );

                        if ( ( $node = eZContentObjectTreeNode::fetch( $nodeID ) ) !== null )
                            return $node->attribute( 'url_alias' );
                    }
                }
            }
        }
        return $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_url_alias' )];
    }

    /**
     * Adds a content object to the Solr search server.
     *
     * @param eZContentObject $contentObject object to add to search engine.
     * @param boolean $commit commit flag. Set if commit should be run after
     *        adding object. If commit flag is set, run optimize() as well every
     *        1000nd time this function is run.
     * @param bool
    */
    function addObject( $contentObject, $commit = true )
    {
        // Add all translations to the document list
        $docList = array();

        // Check if we need to index this object after all
        // Exclude if class identifier is in the exclude list for classes
        $excludeClasses = $this->FindINI->variable( 'IndexExclude', 'ClassIdentifierList' );
        if ( $excludeClasses && in_array( $contentObject->attribute( 'class_identifier' ), $excludeClasses ) )
        {
            return true;
        }
        // Get global object values
        $mainNode = $contentObject->attribute( 'main_node' );
        // initialize array of parent node path ids, needed for multivalued path field and subtree filters
        $nodePathArray = array();
        if ( !$mainNode )
        {
            eZDebug::writeError( 'Unable to fetch main node for object: ' . $contentObject->attribute( 'id' ), 'eZSolr::addObject()' );
            return false;
        }
        //included in $nodePathArray
        //$pathArray = $mainNode->attribute( 'path_array' );
        $currentVersion = $contentObject->currentVersion();

        // Get object meta attributes.
        $metaAttributeValues = self::getMetaAttributesForObject( $contentObject );

        // Get node attributes.
        $nodeAttributeValues = array();
        foreach( $contentObject->attribute( 'assigned_nodes' ) as $contentNode )
        {
            foreach( eZSolr::nodeAttributes() as $attributeName => $fieldType )
            {
                $nodeAttributeValues[] = array( 'name' => $attributeName,
                                                'value' => $contentNode->attribute( $attributeName ),
                                                'fieldType' => $fieldType );
            }
            $nodePathArray[] = $contentNode->attribute( 'path_array' );

        }

        // Check anonymous user access.
        if ( $this->FindINI->variable( 'SiteSettings', 'IndexPubliclyAvailable' ) == 'enabled' )
        {
            $anonymousUserID = $this->SiteINI->variable( 'UserSettings', 'AnonymousUserID' );
            $currentUserID = eZUser::currentUserID();
            $user = eZUser::instance( $anonymousUserID );
            eZUser::setCurrentlyLoggedInUser( $user, $anonymousUserID );
            $anonymousAccess = $contentObject->attribute( 'can_read' );
            $user = eZUser::instance( $currentUserID );
            eZUser::setCurrentlyLoggedInUser( $user, $currentUserID );
            $anonymousAccess = $anonymousAccess ? 'true' : 'false';
        }
        else
        {
            $anonymousAccess = 'false';
        }

        // Load index time boost factors if any
        //$boostMetaFields = $this->FindINI->variable( "IndexBoost", "MetaField" );
        $boostClasses = $this->FindINI->variable( 'IndexBoost', 'Class' );
        $boostAttributes = $this->FindINI->variable( 'IndexBoost', 'Attribute' );
        $boostDatatypes = $this->FindINI->variable( 'IndexBoost', 'Datatype' );
        $reverseRelatedScale = $this->FindINI->variable( 'IndexBoost', 'ReverseRelatedScale' );

        // Initialise default doc boost
        $docBoost = 1.0;
        $contentClassIdentifier = $contentObject->attribute( 'class_identifier' );
        // Just test if the boost factor is defined by checking if it has a numeric value
        if ( isset( $boostClasses[$contentClassIdentifier] ) && is_numeric( $boostClasses[$contentClassIdentifier] ) )
        {
            $docBoost += $boostClasses[$contentClassIdentifier];
        }
        // Google like boosting, using eZ Publish reverseRelatedObjectCount
        $reverseRelatedObjectCount = $contentObject->reverseRelatedObjectCount();
        $docBoost += $reverseRelatedScale * $reverseRelatedObjectCount;

        //  Create the list of available languages for this version :
        $availableLanguages = $currentVersion->translationList( false, false );

        // Loop over each language version and create an eZSolrDoc for it
        foreach( $availableLanguages as $languageCode )
        {
            $doc = new eZSolrDoc( $docBoost );
            // Set global unique object ID
            $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'guid' ), $this->guid( $contentObject, $languageCode ) );

            // Set installation identifier
            $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'installation_id' ), self::installationID() );
            $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'installation_url' ),
                            $this->FindINI->variable( 'SiteSettings', 'URLProtocol' ) . $this->SiteINI->variable( 'SiteSettings', 'SiteURL' ) . '/' );

            // Set Object attributes
            $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'name' ), $contentObject->name( false, $languageCode ) );
            $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'anon_access' ), $anonymousAccess );
            $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'language_code' ), $languageCode );
            $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'available_language_codes' ), $availableLanguages );

            if ( $owner = $contentObject->attribute( 'owner' ) )
            {
                // Set owner name
                $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'owner_name' ),
                                $owner->name( false, $languageCode ) );

                // Set owner group ID
                foreach( $owner->attribute( 'parent_nodes' ) as $groupID )
                {
                    $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'owner_group_id' ), $groupID );
                }
            }

            // from eZ Publish 4.1 only: object states
            // so let's check if the content object has it
            if (method_exists( $contentObject, 'stateIDArray'))
            {
                $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'object_states' ),
                                $contentObject->stateIDArray() );
            }

            // Set content object meta attribute values.
            foreach ( $metaAttributeValues as $metaInfo )
            {
                $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( $metaInfo['name'] ),
                                ezfSolrDocumentFieldBase::preProcessValue( $metaInfo['value'], $metaInfo['fieldType'] ) );
            }

            // Set content node meta attribute values.
            foreach ( $nodeAttributeValues as $metaInfo )
            {
                $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( $metaInfo['name'] ),
                                ezfSolrDocumentFieldBase::preProcessValue( $metaInfo['value'], $metaInfo['fieldType'] ) );
            }

            // Add main url_alias
            $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_url_alias' ), $mainNode->attribute( 'url_alias' ) );

            // add nodeid of all parent nodes path elements
            foreach ( $nodePathArray as $pathArray )
            {
                foreach ( $pathArray as $pathNodeID)
                {
                    $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'path' ), $pathNodeID );
                }
            }

            eZContentObject::recursionProtectionStart();

            // Loop through all eZContentObjectAttributes and add them to the Solr document.
            foreach ( $currentVersion->contentObjectAttributes( $languageCode ) as $attribute )
            {
                $metaDataText = '';
                $classAttribute = $attribute->contentClassAttribute();
                $attributeIdentifier = $classAttribute->attribute( 'identifier' );
                $combinedIdentifier = $contentClassIdentifier . '/' . $attributeIdentifier;
                $boostAttribute = false;
                if ( isset( $boostAttributes[$attributeIdentifier]) && is_numeric( $boostAttributes[$attributeIdentifier]))
                {
                    $boostAttribute = $boostAttributes[$attributeIdentifier];
                }
                if ( isset( $boostAttributes[$combinedIdentifier]) && is_numeric( $boostAttributes[$combinedIdentifier]))
                {
                    $boostAttribute += $boostAttributes[$combinedIdentifier];
                }
                if ( $classAttribute->attribute( 'is_searchable' ) == 1 )
                {
                    $documentFieldBase = ezfSolrDocumentFieldBase::getInstance( $attribute );
                    $this->addFieldBaseToDoc( $documentFieldBase, $doc, $boostAttribute );
                }
            }
            eZContentObject::recursionProtectionEnd();

            $docList[$languageCode] = $doc;
        }

        $optimize = false;
        if ( $this->FindINI->variable( 'IndexOptions', 'DisableDirectCommits' ) === 'true' )
        {
            $commit = false;
        }
        $commitWithin = 0;
        if ( $this->FindINI->variable( 'IndexOptions', 'CommitWithin' ) > 0 )
        {
            $commitWithin = $this->FindINI->variable( 'IndexOptions', 'CommitWithin' );
        }
        if ( $commit && ( $this->FindINI->variable( 'IndexOptions', 'OptimizeOnCommit' ) === 'enabled' ) )
        {
            $optimize = true;
        }
        if ( $this->UseMultiLanguageCores === true)
        {
            foreach( $availableLanguages as $languageCode )
            {
                $this->SolrLanguageShards[$languageCode]->addDocs( array( $docList[$languageCode] ), $commit, $optimize, $commitWithin );
            }
        }
        else
        {
            return $this->Solr->addDocs( $docList, $commit, $optimize, $commitWithin );
        }
        

    }

    /**
     * Add instance of ezfSolrDocumentFieldBase to Solr document.
     *
     * @param ezfSolrDocumentFieldBase Instance of ezfSolrDocumentFieldBase
     * @param eZSolrDoc Solr document
     */
    function addFieldBaseToDoc( ezfSolrDocumentFieldBase $fieldBase, eZSolrDoc $doc, $boost = false )
    {
        $fieldBaseData = $fieldBase->getData();
        if ( empty( $fieldBaseData ) )
        {
            if (is_object($fieldBase) )
            {
                $contentClassAttribute = $fieldBase->ContentObjectAttribute->attribute( 'contentclass_attribute' );
                $fieldName = $fieldBase->getFieldName( $contentClassAttribute );
                $errorMessage = 'empty array for ' . $fieldName;
            }
            else
            {
                $errorMessage = '$fieldBase not an object';
            }
            eZDebug::writeNotice( $errorMessage , 'eZSolr::addFieldBaseToDoc' );
            return false;
        }
        else
        {
           foreach( $fieldBaseData as $key => $value )
           {
                $doc->addField( $key, $value, $boost );
           }
           return true;
        }

    }

    /**
     * Performs a solr COMMIT
     */
    function commit()
    {

        if ( $this->UseMultiLanguageCores === true)
        {
            foreach ($this->SolrLanguageShards as $shard)
            {
                $shard->Solr->commit();
            }
        }
        else
        {
            $this->Solr->commit();
        }
        
    }

    /**
     * Performs a solr OPTIMIZE call
     */
    function optimize( $withCommit = false )
    {

        if ( $this->UseMultiLanguageCores === true)
        {
            foreach ($this->SolrLanguageShards as $shard)
            {
                $shard->optimize( $withCommit );
            }
        }
        else
        {
            $this->Solr->optimize( $withCommit );
        }
    }

    /**
     * Removes an object from the Solr search server
     * 
     * @param eZContentObject $contentObject the content object to remove
     * @param bool $commit wether or not to commit after removing the object
     * 
     * @return bool true if removal was successful
     */
    function removeObject( $contentObject, $commit = null )
    {
        /*
         * @since eZFind 2.2: allow delayed commits if explicitely set as configuration setting and
         * the parameter $commit it is not set
         * Default behaviour is as before
         */
        if (!isset($commit) && ($this->FindINI->variable( 'IndexOptions', 'DisableDeleteCommits' ) === 'true'))
        {
            $commit = false;
        }
        elseif ( !isset($commit) )
        {
            $commit = true;
        }

        // 1: remove the assciated "elevate" configuration
        eZFindElevateConfiguration::purge( '', $contentObject->attribute( 'id' ) );
        //eZFindElevateConfiguration::synchronizeWithSolr();
        $this->pushElevateConfiguration();

        // @todo Remove if accepted. Optimize is bad on runtime.
        $optimize = false;
        if ( $commit && ( $this->FindINI->variable( 'IndexOptions', 'OptimizeOnCommit' ) === 'enabled' ) )
        {
            $optimize = true;
        }

        // 2: create a delete array with all the required infos, groupable by language
        $languages = eZContentLanguage::fetchList();
        foreach( $languages as $language )
        {
            $languageCode = $language->attribute( 'locale' );
            $docs[$languageCode] = $this->guid( $contentObject, $languageCode );
        }
        if ( $this->UseMultiLanguageCores === true)
        {
            foreach($docs as $languageCode => $doc)
            {
                $this->SolrLanguageShards[$languageCode]->deleteDocs( array( $doc ), false, $commit, $optimize );
            }
        }
        else
        {
            return $this->Solr->deleteDocs( $docs, false, $commit, $optimize );
        }
    }

    /**
     * Search on the Solr search server
     * @todo: add functionality not to call the DB to recreate objects : $asObjects == false
     *
     * @param string search term
     * @param array parameters. @see ezfeZPSolrQueryBuilder::buildSearch()
     * @see ezfeZPSolrQueryBuilder::buildSearch()
     * @param array search types. Reserved.
     *
     * @return array List of eZFindResultNode objects.
     */
    function search( $searchText, $params = array(), $searchTypes = array() )
    {
        eZDebug::createAccumulator( 'Search', 'eZ Find' );
        eZDebug::accumulatorStart( 'Search' );
        $error = 'Server not running';
        $searchCount = 0;

        $coreToUse = null;
        $shardQueryPart = null;
        if ( $this->UseMultiLanguageCores === true )
        {
            $languages = $this->SiteINI->variable( 'RegionalSettings', 'SiteLanguageList' );
            if ( array_key_exists ($languages[0], $this->SolrLanguageShards ) )
            {
                $coreToUse = $this->SolrLanguageShards[$languages[0]];
                if ( $this->FindINI->variable( 'LanguageSearch', 'SearchMainLanguageOnly' ) <> 'enabled' )
                {
                    $shardQueryPart = array( 'shards' => implode(',', $this->SolrLanguageShardURIs ));
                }
            }
            //eZDebug::writeNotice( $languages, 'eZSolr::search() languages' );
            eZDebug::writeNotice( $shardQueryPart, 'eZSolr::search() shards' );
            //eZDebug::writeNotice( $this->SolrLanguageShardURIs, 'eZSolr::search() this languagesharduris' );
        }
        else
        {
            $coreToUse = $this->Solr;
        }


        if ( $this->SiteINI->variable( 'SearchSettings', 'AllowEmptySearch' ) == 'disabled' &&
             trim( $searchText ) == '' )
        {
            $error = 'Empty search is not allowed.';
            eZDebug::writeNotice( $error,
                                  'eZSolr::search()' );
            $resultArray = null;
        }
        
        else
        {
            eZDebug::createAccumulator( 'Query build', 'eZ Find' );
            eZDebug::accumulatorStart( 'Query build' );
            $queryBuilder = new ezfeZPSolrQueryBuilder( $this );
            $queryParams = $queryBuilder->buildSearch( $searchText, $params, $searchTypes );
            if (! $shardQueryPart == null )
            {
                $queryParams = array_merge($shardQueryPart, $queryParams);
            }
            eZDebug::accumulatorStop( 'Query build' );
            eZDebug::writeDebug( $queryParams, 'Final query parameters sent to Solr backend' );

            eZDebug::createAccumulator( 'Engine time', 'eZ Find' );
            eZDebug::accumulatorStart( 'Engine time' );
            $resultArray = $coreToUse->rawSearch( $queryParams );
            eZDebug::accumulatorStop( 'Engine time' );
        }

        if (! $resultArray )
        {
            eZDebug::accumulatorStop( 'Search' );
            return array(
                'SearchResult' => false,
                'SearchCount' => 0,
                'StopWordArray' => array(),
                'SearchExtras' => new ezfSearchResultInfo( array( 'error' => ezi18n( 'ezfind', $error ) ) ) );
        }

        $highLights = array();
        if ( !empty( $resultArray['highlighting'] ) )
        {
            foreach ( $resultArray['highlighting'] as $id => $highlight )
            {
                $highLightStrings = array();
                //implode apparently does not work on associative arrays that contain arrays
                //$element being an array as well
                foreach ($highlight as $key => $element)
                {
                    $highLightStrings[] = implode(' ', $element);
                }
                $highLights[$id] = implode(' ...  ', $highLightStrings);

            }
        }
        //if ( count($resultArray) > 0 )
        if ( !empty( $resultArray ) ) //added by nehal
        {
            $result = $resultArray['response'];
            $searchCount = $result['numFound'];
            $maxScore = $result['maxScore'];
            $docs = $result['docs'];
            $localNodeIDList = array();
            $objectRes = array();
            $nodeRowList = array();

            // Loop through result, and get eZContentObjectTreeNode ID
            foreach ( $docs as $idx => $doc )
            {
                if ( $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'installation_id' )] == self::installationID() )
                {
                    //$localNodeIDList[] = $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_node_id' )][0];
                    $localNodeIDList[] = $this->getNodeID( $doc );
                }
            }

            //if ( count( $localNodeIDList ) )
            if ( !empty( $localNodeIDList ) ) //code add by nehal
            {
                $tmpNodeRowList = eZContentObjectTreeNode::fetch( $localNodeIDList, false, false );
                // Workaround for eZContentObjectTreeNode::fetch behaviour
                if ( count( $localNodeIDList ) === 1 )
                {
                    $tmpNodeRowList = array( $tmpNodeRowList );
                }
                if ( $tmpNodeRowList )
                {
                    foreach( $tmpNodeRowList as $nodeRow )
                    {
                        $nodeRowList[$nodeRow['node_id']] = $nodeRow;
                    }
                }
                unset( $tmpNodeRowList );
            }

            foreach ( $docs as $idx => $doc )
            {
                if ( $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'installation_id' )] == self::installationID() )
                {
                    // Search result document is from current installation
//                    var_dump( ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_node_id' ), $doc, $nodeRowList );die();
                    //$resultTree = new eZFindResultNode( $nodeRowList[$doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_node_id' )][0]] );
                    //$resultTree->setContentObject( new eZContentObject( $nodeRowList[$doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_node_id' )][0]] ) );
                    $nodeID = $this->getNodeID( $doc );    

                    $resultTree = new eZFindResultNode( $nodeRowList[$nodeID] );         

                    $resultTree->setContentObject( new eZContentObject( $nodeRowList[$nodeID] ) );
                    
                    $resultTree->setAttribute( 'is_local_installation', true );
                    if ( !$resultTree->attribute( 'can_read' ) )
                    {
                        /*eZDebug::writeNotice( 'Access denied for eZ Find result, node_id: ' . $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_node_id' )][0],
                                              'eZSolr::search()' );*/
                        eZDebug::writeNotice( 'Access denied for eZ Find result, node_id: ' . $nodeID,
                                               'eZSolr::search()' );
                        continue;
                    }

                    $urlAlias = $this->getUrlAlias( $doc );
                    $globalURL = $urlAlias . '/(language)/' . $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'language_code' )];
                    eZURI::transformURI( $globalURL );
                }
                else
                {
                    $resultTree = new eZFindResultNode();
                    $resultTree->setAttribute( 'is_local_installation', false );
                    $globalURL = $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'installation_url' )] .
                        $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_url_alias' )] .
                        '/(language)/' . $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'language_code' )];
                }

                $resultTree->setAttribute( 'name', $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'name' )] );
                $resultTree->setAttribute( 'published', $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'published' )] );
                $resultTree->setAttribute( 'global_url_alias', $globalURL );
                $resultTree->setAttribute( 'highlight', isset( $highLights[$doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'guid' )]] ) ?
                                           $highLights[$doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'guid' )]] : null );
                /**
                 * $maxScore may be equal to 0 when the QueryElevationComponent is used.
                 * It returns as first results the elevated documents, with a score equal to 0. In case no
                 * other document than the elevated ones are returned, maxScore is then 0 and the
                 * division below raises a warning. If maxScore is equal to zero, we can safely assume
                 * that only elevated documents were returned. The latter have an articifial relevancy of 100%,
                 * which must be reflected in the 'score_percent' attribute of the result node.
                 */
                $maxScore != 0 ? $resultTree->setAttribute( 'score_percent', (int) ( ( $doc['score'] / $maxScore ) * 100 ) ) : $resultTree->setAttribute( 'score_percent', 100 );
                $resultTree->setAttribute( 'language_code', $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'language_code' )] );
                $objectRes[] = $resultTree;
            }
        }

        $stopWordArray = array();

        eZDebug::accumulatorStop( 'Search' );
        return array(
            'SearchResult' => $objectRes,
            'SearchCount' => $searchCount,
            'StopWordArray' => $stopWordArray,
            'SearchExtras' => new ezfSearchResultInfo( $resultArray ) );
    }

    /**
     * More like this is pretty similar to normal search, but usually only the object or node id are sent to Solr
     * However, streams or a search text body can also be passed .. Solr will extract the important terms and build a
     * query for us
     * 
     * @param string $queryType is one of 'noid', 'oid', 'url', 'text'
     * @param $queryValue the node id, object id, url or text body to use
     * @param array parameters. @see ezfeZPSolrQueryBuilder::buildMoreLikeThis()
     *
     * @return array List of eZFindResultNode objects.
     * 
     * @todo: add functionality not to call the DB to recreate objects : $asObjects == false
     */
    function moreLikeThis( $queryType, $queryValue, $params = array() )
    {
        eZDebug::createAccumulator( 'MoreLikeThis', 'eZ Find' );
        eZDebug::accumulatorStart( 'MoreLikeThis' );
        $error = 'Server not running';
        $searchCount = 0;
        //mlt does not support distributed search yet, so find out which is 
        //the language core to use and qyery only this one
        //search across languages does not make sense here
        $coreToUse = null;
        if ( $this->UseMultiLanguageCores == true )
        {
            $languages = $this->SiteINI->variable( 'RegionalSettings', 'SiteLanguageList' );
            if ( array_key_exists ($languages[0], $this->SolrLanguageShards ) )
            {
                $coreToUse = $this->SolrLanguageShards[$languages[0]];
            }
        }
        else
        {
            $coreToUse = $this->Solr;
        }

        if ( trim( $queryType ) == '' || trim( $queryValue ) == '' )
        {
            $error = 'Missing query arguments for More Like This: ' . 'querytype = ' . $queryType . ', Query Value = ' . $queryValue;
            eZDebug::writeNotice( $error, __METHOD__ );
            $resultArray = null;
        }
        else
        {
            eZDebug::createAccumulator( 'Query build', 'eZ Find' );
            eZDebug::accumulatorStart( 'Query build' );
            $queryBuilder = new ezfeZPSolrQueryBuilder( $this );
            $queryParams = $queryBuilder->buildMoreLikeThis( $queryType, $queryValue, $params );
            eZDebug::accumulatorStop( 'Query build' );

            eZDebug::createAccumulator( 'Engine time', 'eZ Find' );
            eZDebug::accumulatorStart( 'Engine time' );
            $resultArray = $coreToUse->rawSolrRequest( '/mlt', $queryParams );
            eZDebug::accumulatorStop( 'Engine time' );
        }

        if (! $resultArray )
        {
            eZDebug::accumulatorStop( 'Search' );
            return array(
                'SearchResult' => false,
                'SearchCount' => 0,
                'StopWordArray' => array(),
                'SearchExtras' => new ezfSearchResultInfo( array( 'error' => ezi18n( 'ezfind', $error ) ) ) );
        }
        $objectRes = array();
        if ( isset( $resultArray['response'] ) && is_array( $resultArray['response'] ) )
        {
            $result = $resultArray['response'];
            $searchCount = $result['numFound'];
            $maxScore = $result['maxScore'];
            $docs = $result['docs'];
            $localNodeIDList = array();
            $nodeRowList = array();

            // Loop through result, and get eZContentObjectTreeNode ID
            foreach ( $docs as $idx => $doc )
            {
                if ( $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'installation_id' )] == self::installationID() )
                {
                    $localNodeIDList[] = $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_node_id' )][0];
                }
            }

            if ( count( $localNodeIDList ) )
            {
                $tmpNodeRowList = eZContentObjectTreeNode::fetch( $localNodeIDList, false, false );
                // Workaround for eZContentObjectTreeNode::fetch behaviour
                if ( count( $localNodeIDList ) === 1 )
                {
                    $tmpNodeRowList = array( $tmpNodeRowList );
                }
                if ( $tmpNodeRowList )
                {
                    foreach( $tmpNodeRowList as $nodeRow )
                    {
                        $nodeRowList[$nodeRow['node_id']] = $nodeRow;
                    }
                }
                unset( $tmpNodeRowList );
            }

            foreach ( $docs as $idx => $doc )
            {
                if ( $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'installation_id' )] == self::installationID() )
                {
                    // Search result document is from current installation
//                    var_dump( ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_node_id' ), $doc, $nodeRowList );die();
                    $resultTree = new eZFindResultNode( $nodeRowList[$doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_node_id' )][0]] );
                    $resultTree->setContentObject( new eZContentObject( $nodeRowList[$doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_node_id' )][0]] ) );
                    $resultTree->setAttribute( 'is_local_installation', true );
                    if ( !$resultTree->attribute( 'can_read' ) )
                    {
                        eZDebug::writeNotice( 'Access denied for eZ Find result, node_id: ' . $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_node_id' )][0],
                                              'eZSolr::search()' );
                        continue;
                    }


                    $globalURL = $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_url_alias' )] .
                        '/(language)/' . $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'language_code' )];
                    eZURI::transformURI( $globalURL );
                }
                else
                {
                    $resultTree = new eZFindResultNode();
                    $resultTree->setAttribute( 'is_local_installation', false );
                    $globalURL = $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'installation_url' )] .
                        $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_url_alias' )] .
                        '/(language)/' . $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'language_code' )];
                }

                $resultTree->setAttribute( 'name', $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'name' )] );
                $resultTree->setAttribute( 'published', $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'published' )] );
                $resultTree->setAttribute( 'global_url_alias', $globalURL );
                $resultTree->setAttribute( 'highlight', isset( $highLights[$doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'guid' )]] ) ?
                                           $highLights[$doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'guid' )]] : null );
                $resultTree->setAttribute( 'score_percent', (int) ( ( $doc['score'] / $maxScore ) * 100 ) );
                $resultTree->setAttribute( 'language_code', $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'language_code' )] );
                $objectRes[] = $resultTree;
            }
        }

        $stopWordArray = array();

        eZDebug::accumulatorStop( 'Search' );
        eZDebug::writeDebug( $resultArray['interestingTerms'], 'MoreLikeThis terms' );
        return array(
            'SearchResult' => $objectRes,
            'SearchCount' => $searchCount,
            'StopWordArray' => $stopWordArray,
            'SearchExtras' => new ezfSearchResultInfo( $resultArray ) );
    }

    /**
     * Initialise / rebuild the Spell checker
     * not needed in current implementation with an index based spell checker
     * and autorebuilds upon commits
     *
     * @package unfinished
     * @return array Solr result set.
     */
    function initSpellChecker()
    {

        if ( $this->UseMultiLanguageCores == true)
        {
            foreach($SolrLanguageShards as $shard )
            {
                $shard->rawSearch( array( 'q' => 'solr', 'qt' => 'spellchecker', 'wt' => 'php', 'cmd' => 'rebuild') );
                //@TODO: process individual results, implement an ezfind error class or reuse ezp ones
                return true;
            }
        }
        else
        {
            $return = $this->Solr->rawSearch( array( 'q' => 'solr', 'qt' => 'spellchecker', 'wt' => 'php', 'cmd' => 'rebuild') );
        }


    }

    /**
     * Experimental: search independent spell check
     * use spellcheck option in search for spellchecking search results
     *
     * @package unfinished
     * @return array Solr result set.
     * @todo: configure different spell check handlers and handle multicore configs (need a parameter for it)
     *
     */
    function spellCheck ( $string, $onlyMorePopular = false, $suggestionCount = 1, $accuracy=0.5 )
    {
        if (! $this->UseMultiLanguageCores)
        {
            $onlyMorePopularString = $onlyMorePopular ? 'true' : 'false';
            return $this->Solr->rawSearch( array( 'q' => $string, 'qt' => 'spellchecker',
                                 'suggestionCount' => $suggestionCount, 'wt' => 'php',
                                 'accuracy' => $accuracy, 'onlyMorePopular' => $onlyMorePopularString ) );
        }

    }

    /**
     * Returns the eZ publish installation ID, used by eZ find to identify sites
     * @return string installaiton ID.
     */
    static function installationID()
    {
        if ( !empty( self::$InstallationID ) )
        {
            return self::$InstallationID;
        }
        $db = eZDB::instance();

        $resultSet = $db->arrayQuery( 'SELECT value FROM ezsite_data WHERE name=\'ezfind_site_id\'' );

        if ( count( $resultSet ) >= 1 )
        {
            self::$InstallationID = $resultSet[0]['value'];
        }
        else
        {
            self::$InstallationID = md5( time() . '-' . mt_rand() );
            $db->query( 'INSERT INTO ezsite_data ( name, value ) values( \'ezfind_site_id\', \'' . self::$InstallationID . '\' )' );
        }

        return self::$InstallationID;
    }

    /**
     * Computes the unique ID of a content object language version
     *
     * @param eZContentObject $contentObject The content object
     * @param string $languageCode
     * @return string guid
     */
    function guid( $contentObject, $languageCode = '' )
    {
        return md5( self::installationID() . '-' . $contentObject->attribute( 'id' ) . '-' . $languageCode );
    }

    /**
     * Clean up search index for current installation.
     * @return bool true if cleanup was successful
     * @todo:  handle multicore configs (need a parameter for it) for return values
    **/
    function cleanup( $allInstallations = false, $optimize = false )
    {
        if ( $allInstallations === true )
        {
            $optimize = true;
            $deleteQuery = '*:*';
        }
        else
        {
            $deleteQuery = ezfSolrDocumentFieldBase::generateMetaFieldName( 'installation_id' ) . ':' . self::installationID();
        }
        if ($this->UseMultiLanguageCores == true)
        {
            foreach($this->SolrLanguageShards as $shard )
            {
                $shard->deleteDocs( array(), $deleteQuery, true, $optimize );
            }
            return true;
        }
        else
        {
            return $this->Solr->deleteDocs( array(), $deleteQuery, true );
        }

    }

    /**
     * For advanced search
     */
    public function supportedSearchTypes()
    {
        $searchTypes = array( array( 'type' => 'attribute',
                                     'subtype' =>  'fulltext',
                                     'params' => array( 'classattribute_id', 'value' ) ),
                              array( 'type' => 'attribute',
                                     'subtype' =>  'patterntext',
                                     'params' => array( 'classattribute_id', 'value' ) ),
                              array( 'type' => 'attribute',
                                     'subtype' =>  'integer',
                                     'params' => array( 'classattribute_id', 'value' ) ),
                              array( 'type' => 'attribute',
                                     'subtype' =>  'integers',
                                     'params' => array( 'classattribute_id', 'values' ) ),
                              array( 'type' => 'attribute',
                                     'subtype' =>  'byrange',
                                     'params' => array( 'classattribute_id' , 'from' , 'to'  ) ),
                              array( 'type' => 'attribute',
                                     'subtype' => 'byidentifier',
                                     'params' => array( 'classattribute_id', 'identifier', 'value' ) ),
                              array( 'type' => 'attribute',
                                     'subtype' => 'byidentifierrange',
                                     'params' => array( 'classattribute_id', 'identifier', 'from', 'to' ) ),
                              array( 'type' => 'attribute',
                                     'subtype' => 'integersbyidentifier',
                                     'params' => array( 'classattribute_id', 'identifier', 'values' ) ),
                              array( 'type' => 'fulltext',
                                     'subtype' => 'text',
                                     'params' => array( 'value' ) ) );
        $generalSearchFilter = array( array( 'type' => 'general',
                                             'subtype' => 'class',
                                             'params' => array( array( 'type' => 'array',
                                                                       'value' => 'value'),
                                                                'operator' ) ),
                                      array( 'type' => 'general',
                                             'subtype' => 'publishdate',
                                             'params'  => array( 'value', 'operator' ) ),
                                      array( 'type' => 'general',
                                             'subtype' => 'subtree',
                                             'params'  => array( array( 'type' => 'array',
                                                                        'value' => 'value'),
                                                                 'operator' ) ) );
        return array( 'types' => $searchTypes,
                      'general_filter' => $generalSearchFilter );
    }

    /**
     * Gets engine text
     *
     * @return string engine text
     */
    static function engineText()
    {
        return ezi18n( 'ezfind', 'eZ Find 2.2 search plugin &copy; 1999-2010 eZ Systems AS, powered by Apache Solr 1.4' );
    }

    /**
     * @see eZSearch::needCommit()
     * @return boolean
     */
    public function needCommit()
    {
        return true;
    }

    /**
     * @see eZSearch::needRemoveWithUpdate()
     * @return boolean
     */
    public function needRemoveWithUpdate()
    {
        return false;
    }

    /**
     * Called when a new section is assigned to an object, trough a node.
     * Simply re-index for now
     *
     * @todo: defer to cron if there are children involved and re-index these too
     * @todo when Solr supports it: update fields only
     *
     * @return void
     * @see eZSearch::updateNodeSection()
     */
    public function updateNodeSection( $nodeID, $sectionID )
    {
        $contentObject = eZContentObject::fetchByNodeID( $nodeID );
        $this->addObject( $contentObject );
    }

    /**
     * Called when a node's visibility is modified.
     * Simply re-index for now.
     *
     * @todo: defer to cron if there are children involved and re-index these too
     * @todo when Solr supports it: update fields only
     *
     * @param $nodeID
     * @param $action
     * @return void
     * @see eZSearch::updateNodeVisibility()
     */
    public function updateNodeVisibility( $nodeID, $action )
    {
        $contentObject = eZContentObject::fetchByNodeID( $nodeID );
        $this->addObject( $contentObject );
    }

    /**
     * Called when a node assignement is added to an object.
     * Simply re-index for now.
     *
     * @todo: defer to cron if there are children involved and re-index these too
     * @todo when Solr supports it: update fields only
     *
     * @param $mainNodeID
     * @param $objectID
     * @param $nodeAssignmentIDList
     * @return unknown_type
     * @see eZSearch::addNodeAssignment()
     */
    public function addNodeAssignment( $mainNodeID, $objectID, $nodeAssignmentIDList )
    {
        $contentObject = eZContentObject::fetch( $objectID );
        $this->addObject( $contentObject );
    }

    /**
     * Called when a node assignement is removed of an object's.
     * Simply re-index for now.
     *
     * @todo: defer to cron if there are children involved and re-index these too
     * @todo when Solr supports it: update fields only
     *
     * @param $mainNodeID
     * @param $objectID
     * @param $nodeAssignmentIDList
     * @return unknown_type
     * @see eZSearch::removeNodeAssignment()
     */
    public function removeNodeAssignment( $mainNodeID, $newMainNodeID, $objectID, $nodeAssigmentIDList )
    {
        $contentObject = eZContentObject::fetch( $objectID );
        $this->addObject( $contentObject );
    }

    /**
     * Called when two nodes are swapped.
     * Simply re-index for now.
     *
     * @todo when Solr supports it: update fields only
     *
     * @param $nodeID
     * @param $selectedNodeID
     * @param $nodeIdList
     * @return void
     */
    public function swapNode( $nodeID, $selectedNodeID, $nodeIdList = array() )
    {
        $contentObject1 = eZContentObject::fetchByNodeID( $nodeID );
        $contentObject2 = eZContentObject::fetchByNodeID( $selectedNodeID );
        $this->addObject( $contentObject1 );
        $this->addObject( $contentObject2 );
    }

    /**
     * update search index upon object state changes:
     * simply re-index for now
     * @todo: defer to cron if there are children involved and re-index these too
     * @todo when Solr supports it: update fields only
     */
    public function updateObjectState( $objectID, $objectStateList )
    {
        $contentObject = eZContentObject::fetch( $objectID );
        $this->addObject( $contentObject );
    }

    private function initLanguageShards()
    {
        $this->SolrLanguageShards = array();
        if ( $this->UseMultiLanguageCores == true )
        {
            
            $languages = $this->SiteINI->variable( 'RegionalSettings', 'SiteLanguageList' );
            $languageMapping = $this->FindINI->variable( 'LanguageSearch','LanguagesCoresMap');
            $shardMapping = $this->SolrINI->variable ('SolrBase', 'Shards');
            foreach ($languages as $language)
            {
                $fullURI=$shardMapping[$languageMapping[$language]];
                $this->SolrLanguageShards[$language]=new eZSolrBase($shardMapping[$languageMapping[$language]]);
                $parts = explode( '://', $fullURI );
                $this->SolrLanguageShardURIs[$language]= $parts[1];
            }



        }
        else
        //pre-2.2 behaviour
        {
            $this->Solr = new eZSolrBase();
            //$this->SolrLanguageShards[] = new eZSolrBase();
        }


    }
    
    /*code add by nehal*/
    
    /* Returns the relative URL Alias for a given search result, depending on whether a subtree filter was applied or not. @param array $doc The search result, directly received from Solr.
        @return int The NodeID corresponding the search result */          

    protected function getNodeID( $doc )    
    {
        if ( isset( $this->postSearchProcessingData['subtree_array'] ) and !empty( $this->postSearchProcessingData['subtree_array'] ) )
        {            
            foreach ( $this->postSearchProcessingData['subtree_array'] as $subtree )
            {
                foreach ( $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'path_string' )] as $pathString )
               {
                       if ( substr_count( $pathString, '/' . $subtree . '/' ) > 0 )
                    {
                        $nodeArray = explode( '/', rtrim( $pathString, '/' ));
                           return (int) array_pop( $nodeArray );
                    }
              }           

          }           

        }     

        return (int) $doc[ezfSolrDocumentFieldBase::generateMetaFieldName( 'main_node_id' )][0];

      }
    
    /*code add by nehal*/
    
    /**
     * synchronises elevate configuration across language shards in case of
     * multiple lnguage indexes, or the default one
     *
     * @TODO: handle exceptions properly
     */
    public function pushElevateConfiguration()
    {
        if ( $this->UseMultiLanguageCores == true )
        {
            foreach( $this->SolrLanguageShards as $shard )
            {
                eZFindElevateConfiguration::synchronizeWithSolr( $shard );
            }
            return true;
        }
        else
        {
            return eZFindElevateConfiguration::synchronizeWithSolr( $this->Solr );
        }

    }

    /**
     * eZSolrBase instance used for interaction with the solr server
     * @var eZSolrBase
     */
    var $Solr;
    var $UseMultiLanguageCores;

    /**
    * @since eZ Find2.2, this holds an array of eZSolrBase objects
    * for multilingual indexes served from different shards
    * if this is enabled
    */
    var $SolrLanguageShards;
    var $SolrLanguageShardURIs;
    /// Object vars
    var $SolrINI;
    var $FindINI;
    var $SiteINI;
    var $SolrDocumentFieldBase;

    /**
     * @since eZ Find 2.1
     *
     * Used to store useful data/metadata for post search processing.
     * Will mostly be updated by the query builder. Keys should be named after the fetch function parameters,
     * when applicable.
     *
     * Example : Knowing which subtress were used as filters allows
     *           for picking the right URL for a potentially multi-located
     *           search result.
     *
     * Example :
     * <code>
     *     array( 'subtree_array' => array( 2, 43 ) );
     * </code>
     *
     * @see ezfeZPSolrQueryBuilder::searchPluginInstance
     * @var array
     */
    public $postSearchProcessingData = array();

    static $InstallationID;
    static $SolrDocumentFieldName;
    // @since ezfind 2.2, information
    public static $fieldTypeContexts = array ('search' => 'DatatypeMap', 'facet' => 'DatatypeMapFacet', 'sort' => 'DatatypeMapSort', 'filter' => 'DatatypeMapFilter');

}

eZSolr::$SolrDocumentFieldName = new ezfSolrDocumentFieldName();

?>

Monday 04 June 2012 12:26:52 pm

Hi Nehal, and thanks for sharing your solution. 

Is it solving the 'main_node_only'  issue that Philipp mentioned ?

Anyways, it would be great to have a dedicate bug-report in the issue tracker if you think that this one : http://issues.ez.no/17576 is not covering your case.

Also : feel free to contribute your finding through a pull-request (more information on this here : http://share.ez.no/learn/ez-publish/how-to-contribute-to-ez-publish-using-git ).

Cheers !

expandshrink

You must be logged in to post messages in this topic!

36 542 Users on board!

Forums menu