SlideShare a Scribd company logo
Apache Solr
Search Mastery
Peter Wolanin and Robert Douglass
                               25. aug 13:30
                               Trellon
We	
  hope	
  you	
  will	
  leave	
  having	
  
                learned	
  about:

•   What	
  is	
  Solr	
  and	
  how	
  do	
  you	
  run	
  it	
  locally
•   Ge9ng	
  Drupal	
  data	
  into	
  Solr
•   Changes	
  in	
  Drupal	
  7
•   Field	
  API	
  integraAon
•   Searching	
  Solr	
  from	
  Drupal
•   Modifying	
  what’s	
  searched	
  and	
  the	
  results
•   Theming	
  search	
  results
Drupal	
  Interacts	
  with	
  Solr	
  via	
  HTTP
•    Drupal	
  sends	
  data	
  to	
  Solr	
  as	
  XML	
  documents
•    Solr	
  accepts	
  documents	
  POSTed	
  to	
  /update
•    A	
  different	
  XML	
  can	
  be	
  POSTed	
  to	
  delete
•    Searching,	
  etc	
  are	
  GET	
  requests
•    If	
  something	
  is	
  not	
  working	
  as	
  expected,	
  you	
  
           can	
  try	
  searching	
  directly	
  in	
  Solr	
  via	
  URL
•    Solr	
  also	
  includes	
  admin	
  and	
  analysis	
  interfaces	
  
           (you	
  need	
  to	
  lock	
  this	
  down	
  for	
  producAon).
Run	
  Solr	
  Using	
  the	
  Example	
  Dir


                     Replace the schema.xml and
                     solrconfig.xml with the ones from
                     the Drupal module



                         Invoke the start.jar:

                         java -jar start.jar
Schema:	
  Defines	
  Types	
  &	
  Fields
<?xml version="1.0" encoding="UTF-8" ?>
<schema name="drupal-0.9.5" version="1.2">
  <types>
    ...
 </types>
 <fields>
<!-- The document id is derived from a site-spcific key (hash) and the node ID like:
     $document->id = $hash . '/node/' . $node->nid; -->
   <field name="id" type="string" indexed="true" stored="true" required="true" />
<!-- These are the fields that correspond to a Drupal node. -->
   <field name="site" type="string" indexed="true" stored="true"/>
   <field name="hash" type="string" indexed="true" stored="true"/>
   <field name="url" type="string" indexed="true" stored="true"/>
   <field name="title" type="text" indexed="true" stored="true" termVectors="true"
           omitNorms="true"/>
   <field name="sort_title" type="sortString" indexed="true" stored="false"/>
   <field name="body" type="text" indexed="true" stored="true" termVectors="true"/>
   <field name="teaser" type="text" indexed="false" stored="true"/>
   ...
 </fields>
 <uniqueKey>id</uniqueKey>
 <!-- field for the QueryParser to use when an explicit fieldname is absent -->
 <defaultSearchField>body</defaultSearchField>

 <!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
 <solrQueryParser defaultOperator="AND"/>
</schema>
Schema:	
  Defines	
  Types	
  &	
  Fields

<field name="id" type="string" indexed="true"
 stored="true" required="true" />
<!-- These are the fields that correspond to a
Drupal node. -->
<field name="site" type="string" indexed="true"
 stored="true"/>
<field name="hash" type="string" indexed="true"
 stored="true"/>
Dynamic	
  Fields	
  Provide	
  Flexibility
  <!-- Dynamic field definitions will be used if the name matches any of the patterns.
       The glob-like pattern in the name attribute must have "*" only at the start or the end.
       Longer patterns will be matched first.   -->

  <dynamicField   name="is_*" type="integer" indexed="true"     stored="true" multiValued="false"/>
  <dynamicField   name="im_*" type="integer" indexed="true"     stored="true" multiValued="true"/>
...
  <dynamicField   name="ss_*" type="string"    indexed="true"   stored="true" multiValued="false"/>
  <dynamicField   name="ts_*" type="text"      indexed="true"   stored="true" multiValued="false"
                  termVectors="true"/>
  <dynamicField   name="ds_*" type="date"  indexed="true" stored="true" multiValued="false"/>
  <dynamicField   name="dm_*" type="date"  indexed="true" stored="true" multiValued="true"/>
  <dynamicField   name="tds_*" type="tdate"indexed="true" stored="true" multiValued="false"/>
  <dynamicField   name="tdm_*" type="tdate"indexed="true" stored="true" multiValued="true"/>
  <dynamicField   name="bm_*" type="boolean"
                                           indexed="true" stored="true" multiValued="true"/>
  <dynamicField   name="bs_*" type="boolean"
                                           indexed="true" stored="true" multiValued="false"/>
...
  <!-- Sortable version of the dynamic string field -->
  <dynamicField name="sort_ss_*" type="sortString" indexed="true" stored="false"/>
  <copyField source="ss_*" dest="sort_ss_*"/>
 <!-- A random sort field -->
  <dynamicField name="random_*" type="rand" indexed="true" stored="true"/>
  <!-- This field is used to store node access records, as opposed to CCK field data -->
  <dynamicField name="nodeaccess*" type="integer" indexed="true" stored="false"
                multiValued="true"/>

  <dynamicField name="*" type="ignored" multiValued="true" />
Dynamic	
  Fields	
  Provide	
  Flexibility
<!-- Dynamic field definitions will be used
if the name matches any of the patterns.
The glob-like pattern in the name attribute must
have "*" only at the start or the end.
Longer patterns will be matched first.   -->

<dynamicField name="is_*" type="integer"
 indexed="true" stored="true"
 multiValued="false"/>
<dynamicField name="im_*" type="integer"
 indexed="true" stored="true"
 multiValued="true"/>
Dynamic	
  Fields	
  Provide	
  Flexibility
  <!-- Dynamic field definitions will be used if the name matches any of the patterns.
       The glob-like pattern in the name attribute must have "*" only at the start or the end.
       Longer patterns will be matched first.   -->

  <dynamicField   name="is_*" type="integer" indexed="true"     stored="true" multiValued="false"/>
  <dynamicField   name="im_*" type="integer" indexed="true"     stored="true" multiValued="true"/>
...
  <dynamicField   name="ss_*" type="string"    indexed="true"   stored="true" multiValued="false"/>
  <dynamicField   name="ts_*" type="text"      indexed="true"   stored="true" multiValued="false"
                  termVectors="true"/>
  <dynamicField   name="ds_*" type="date"  indexed="true" stored="true" multiValued="false"/>
  <dynamicField   name="dm_*" type="date"  indexed="true" stored="true" multiValued="true"/>
  <dynamicField   name="tds_*" type="tdate"indexed="true" stored="true" multiValued="false"/>
  <dynamicField   name="tdm_*" type="tdate"indexed="true" stored="true" multiValued="true"/>
  <dynamicField   name="bm_*" type="boolean"
                                           indexed="true" stored="true" multiValued="true"/>
  <dynamicField   name="bs_*" type="boolean"
                                           indexed="true" stored="true" multiValued="false"/>
...
  <!-- Sortable version of the dynamic string field -->
  <dynamicField name="sort_ss_*" type="sortString" indexed="true" stored="false"/>
  <copyField source="ss_*" dest="sort_ss_*"/>
 <!-- A random sort field -->
  <dynamicField name="random_*" type="rand" indexed="true" stored="true"/>
  <!-- This field is used to store node access records, as opposed to CCK field data -->
  <dynamicField name="nodeaccess*" type="integer" indexed="true" stored="false"
                multiValued="true"/>

  <dynamicField name="*" type="ignored" multiValued="true" />
Dynamic	
  Fields	
  Provide	
  Flexibility
<!-- Sortable version of the dynamic
     string field -->
<dynamicField name="sort_ss_*" type="sortString"
 indexed="true" stored="false"/>
<copyField source="ss_*" dest="sort_ss_*"/>

<!-- This field is used to store node access
 records, as opposed to CCK field data -->
<dynamicField name="nodeaccess*"
 type="integer" indexed="true" stored="false"
 multiValued="true"/>

<dynamicField name="*" type="ignored"
 multiValued="true" />
The $query object
Use the factory method to get an object for
building your queries:

$query = apachesolr_drupal_query(
   $keys = '',
   $filters = '',
   $solrsort = '',
   $base_path = '',
   $solr = NULL
);
The actual class that is returned is
determined by a Drupal variable:



variable_get('apachesolr_query_class',
array('apachesolr', 'Solr_Base_Query'));
interface Drupal_Solr_Query_Interface {
  get_filters($name);

    has_filter($field, $value);

    add_filter($field, $value, $exclude);

    remove_filter($field, $value);

    ...
}
interface Drupal_Solr_Query_Interface {
  ...

    get_keys();

    set_keys($keys);

    remove_keys();

    ...
}
interface Drupal_Solr_Query_Interface {
  ...

    get_path();

    get_url_queryvalues();

    get_query_basic();

    ...
}
interface Drupal_Solr_Query_Interface {
  ...

    get_available_sorts();

    set_available_sort($field, $sort);

    get_solrsort();

    set_solrsort($field, $direction);
    ...
}
interface Drupal_Solr_Query_Interface {
  ...

    add_subquery(
     Drupal_Solr_Query_Interface $query);

    remove_subquery(
     Drupal_Solr_Query_Interface $query);

    remove_subqueries();
    ...
}
interface Drupal_Solr_Query_Interface {
  ...

    // Passes to the $solr object which
    // executes the search.
    search($keys = NULL);

}
The $solr object
Use the factory method to get an object for
sending requests to Solr:



$solr =
 apachesolr_get_solr($host, $port, $path);
The actual class that is returned is
determined by a Drupal variable:



variable_get('apachesolr_service_class',
   array('apachesolr',
         'Drupal_Apache_Solr_Service.php',
         'Drupal_Apache_Solr_Service')
);
This allows you to customize the way
search works by providing a different solr
service class than the standard.


variable_set('apachesolr_service_class',
  array('acquia_search',
         'Acquia_Search_Service.php',
         'Acquia_Search_Service')
);
http://code.google.com/p/solr-php-client/

class Apache_Solr_Service {

    addDocument(
        Apache_Solr_Document $document);
    addDocuments($documents);
    deleteById($id);
    deleteByQuery($rawQuery);
    ...
}
http://code.google.com/p/solr-php-client/

class Apache_Solr_Service {
 ...

    ping();
    commit();
    optimize();

    ...
}
http://code.google.com/p/solr-php-client/

class Apache_Solr_Service {

    // Builds a GET request.
    search();

}
class Drupal_Apache_Solr_Service
 extends Apache_Solr_Service {

    getLuke();
    getFields();
    getStatsSummary();

    ...
}
class Drupal_Apache_Solr_Service
 extends Apache_Solr_Service {

    // Takes control of the request sending
    // and headers - Drupal idiomatic.
    _makeHttpRequest();

}
The $document object
http://code.google.com/p/solr-php-client/

class Apache_Solr_Document {

    addField($key, $value, $boost);
    setMultiValue($key, $value, $boost);

}
Drupal	
  7	
  Changes	
  

    $query, $params                      $query->params

    $solr->search()                      $query->search()


•   Taxonomy	
  on	
  a	
  node	
  is	
  now	
  a	
  term	
  reference	
  field	
  
      (works	
  as	
  part	
  of	
  the	
  Field	
  API	
  integraAon).
•   Fixes	
  to	
  core	
  search	
  module	
  APIs	
  mean	
  that	
  some	
  
      hacks	
  are	
  gone:	
  e.g.	
  no,	
  hook_menu_alter;	
  we	
  
      can	
  set	
  apachesolr	
  as	
  the	
  default	
  via	
  search	
  UI.
You	
  Can	
  Add	
  Any	
  Data	
  to	
  the	
  Index
hook_apachesolr_update_index(&$document,
$node, $namespace)

•    Used	
  to	
  add	
  more	
  data	
  to	
  a	
  document	
  before	
  
       it’s	
  sent	
  to	
  Solr.
•    Can	
  also	
  be	
  used	
  to	
  alter	
  or	
  replace	
  data	
  added	
  
       by	
  apachesolr	
  or	
  another	
  module.
•    This	
  is	
  it!	
  (it	
  works	
  like	
  an	
  _alter	
  hook).
Image	
  Data	
  Using	
  Dynamic	
  Fields
/**
  * Implementation of hook_apachesolr_update_index().
  */
function apachesolr_image_apachesolr_update_index(&$document, $node, $namespace) {
   if ($node->type == 'image' && $document->entity == 'node') {
     $areas = array();
     $sizes = image_get_derivative_sizes($node->images['_original']);
     foreach ($sizes as $name => $info) {
       $areas[$name] = $info['width'] * $info['height'];
     }
     asort($areas);
     $image_path = FALSE;
     foreach ($areas as $preset => $size) {
       $image_path = $node->images[$preset];
       break;
     }
     if ($image_path) {
       $document->ss_image_relative = $image_path;
       // Support multi-site too.
       $document->ss_image_absolute = file_create_url($image_path);
     }
   }
}

/**
  * Implementation of hook_apachesolr_modify_query().
  */
function apachesolr_image_apachesolr_modify_query($query, $caller) {
   // Also retrieve image thumbnail links.
   $query->params['fl'] .= ',ss_image_relative';
}
Image	
  Data	
  Using	
  Dynamic	
  Fields
 if ($image_path) {
   $document->ss_image_relative = $image_path;
 }

/**
  * Implement hook_apachesolr_modify_query().
  */
function
apachesolr_image_apachesolr_modify_query(
$query, $caller) {
   // Also retrieve image thumbnail links.
   $query->params['fl'] .= ',ss_image_relative';
}
UI	
  to	
  Exclude	
  Whole	
  Content	
  Types
•   ?q=admin/config/search/apachesolr/content-­‐bias
Control	
  Indexing	
  More	
  Precisely	
  
hook_apachesolr_node_exclude($node, $namespace)

in_array($node->type, variable_get(
'apachesolr_exclude_comments_types', array()))

hook_node_update_index($node)

•   hook_node_update_index	
  output	
  added	
  to	
  body.
•   We	
  can	
  create	
  mulAple	
  documents	
  from	
  one	
  node	
  
      (e.g.	
  document	
  per	
  comment).
hook_apachesolr_document_handlers($type,
$namespace)
Field	
  API	
  IntegraAon
•   Most	
  of	
  the	
  Field	
  API	
  integraAon	
  follows	
  
       directly	
  from	
  the	
  6.x-­‐2.x	
  CCK	
  integraAon.
•   In	
  Drupal	
  7,	
  we	
  match	
  field	
  types,	
  rather	
  than	
  
       looking	
  at	
  the	
  widget.
•   By	
  default,	
  the	
  data	
  will	
  be	
  indexed	
  to	
  Solr	
  as	
  
       mulA-­‐valued,	
  and	
  named	
  combining	
  the	
  field	
  
       module	
  and	
  name	
  sm_$module_$fieldname
Typically	
  need	
  4	
  things:
•   What	
  field	
  types	
  (or	
  field	
  instances)	
  to	
  look	
  
         for	
  during	
  indexing.
•   The	
  data	
  type	
  to	
  use	
  in	
  the	
  index	
  
         (index_type)
•   A	
  funcAon	
  for	
  extracAng	
  the	
  data	
  from	
  the	
  
         field	
  while	
  indexing	
  (indexing_callback).
•   A	
  funcAon	
  for	
  displaying	
  the	
  data	
  from	
  the	
  
         field	
  during	
  searches	
  (display_callback).
Field	
  API	
  IntegraAon
hook_apachesolr_field_mappings_alter
(&$mappings)

$mappings['list_text'] = array(
   'display_callback' =>
     'apachesolr_fields_list_display_callback',
   'indexing_callback' =>
     'apachesolr_fields_list_indexing_callback',
   'index_type' =>
     'string',
);
Analysis of an apachesolr search request
   	 
           	 
                search_view()



        $response = $query->search(...)
$results = apachesolr_search_process_response
          ($response,$final_query)


   theme('search_results', $results, ...)
Analysis of an apachesolr search request
   	 
           	 
                search_view()



        $response = $query->search(...)
$results = apachesolr_search_process_response
          ($response,$final_query)


   theme('search_results', $results, ...)
hook_menu: defines custom search paths

/arts

/arts/undergraduate

/search/apachesolr_search/?
filters=type%3Acatalog%20
ss_faculty%3AAR%20sm_level
%3AUndergraduate
hook_menu: defines custom search paths

/arts

/arts/undergraduate

/arts/undergraduate/courses
hook_menu: defines custom search paths




// Implements hook_menu().
function mcgill_menu() {
  $items['arts/undergraduate/courses'] = array(
    'page callback' => 'mcgill_courses_search',
    'access arguments' => array('search content'),
    'type' => MENU_CALLBACK,
  );
   return $items;
}
Analysis of an apachesolr search request
   	 
           	 
                search_view()



        $response = $query->search(...)
$results = apachesolr_search_process_response
          ($response,$final_query)


   theme('search_results', $results, ...)
hook_menu_alter: changes the page callback
hook_menu_alter: changes the page callback
hook_menu_alter: changes the page callback
hook_menu_alter: changes the page callback
hook_menu_alter: changes the page callback




// Implements hook_menu_alter().
function mcgill_menu_alter(&$items) {
  if (isset($items['search/apachesolr_search/%menu_tail'])) {
    $items['search']['page callback'] = 'mcgill_page';
    $items['search/apachesolr_search/%menu_tail']['page callback'] = 'mcgill_page';
  }
}
Analysis of an apachesolr search request
   	 
           	 
                search_view()



        $response = $query->search(...)
$results = apachesolr_search_process_response
          ($response,$final_query)


   theme('search_results', $results, ...)
An example Solr request
Analysis of an apachesolr search request
  	 
          	 
               search_view()



       $response = $query->search(...)
$results = apachesolr_search_process_response
          ($response,$final_query)


   theme('search_results', $results, ...)
hook_apachesolr_prepare_query($query)
Analysis of an apachesolr search request
        	 
                	 
                     search_view()



             $response = $query->search(...)
$results = apachesolr_process_response($response, ...)
     $results = apachesolr_search_process_response
               ($response,$final_query)


       theme('search_results', $results, ...)
hook_apachesolr_prepare/modify_query($query)




// Run hook_apachesolr_prepare_query($query).

// Cache the built query.
$current_query = apachesolr_current_query($query);

// Run hook_apachesolr_modify_query($query).
hook_apachesolr_prepare/modify_query($query)
hook_apachesolr_prepare/modify_query($query)
hook_apachesolr_prepare_query($query):
    set a default Solr sort parameter
hook_apachesolr_prepare_query($query):
            set a default Solr sort parameter



$query->set_available_sort('sort_ss_course_code', array(
  'title' => t('Course code'),
  'default' => 'asc',
));
$query->remove_available_sort('created');
$query->remove_available_sort('sort_name');
$query->remove_available_sort('type');
hook_apachesolr_prepare_query($query):
            set a default Solr sort parameter


if (!isset($_GET['solrsort'])) {
  if ($query->get_keys()) {
    $query->set_solrsort('score', 'asc');
  }
  else {
    $query->set_solrsort('sort_ss_course_code', 'asc');
  }
}
hook_apachesolr_prepare/modify_query($query)
Should I use hook_apachesolr_prepare_query
      or hook_apachesolr_modify_query?




/arts/undergraduate/courses
Should I use hook_apachesolr_prepare_query
    or hook_apachesolr_modify_query?
Should I use hook_apachesolr_prepare_query
    or hook_apachesolr_modify_query?
Should I use hook_apachesolr_prepare_query
    or hook_apachesolr_modify_query?
Should I use hook_apachesolr_prepare_query
    or hook_apachesolr_modify_query?
Should I use hook_apachesolr_prepare_query
    or hook_apachesolr_modify_query?
hook_apachesolr_modify_query($query):
          set default Solr fq parameters


// Add filters for FACULTY/LEVEL/courses paths.
if ($facet = get_faculty_from_path()) {
  $query->add_filter('ss_faculty', $facet);
}
if ($facet = get_level_from_path()) {
  $query->add_filter('sm_level', $facet);
}
hook_apachesolr_prepare/modify_query($query)
hook_apachesolr_prepare/modify_query($query)
      Set Solr parameters in $query->params




$query->params['fl'] .=
',ss_course_code';

$query->params['facet.limit'] = -1;
Analysis of an apachesolr search request
   	 
           	 
                search_view()



        $response = $query->search(...)
$results = apachesolr_search_process_response
          ($response,$final_query)


   theme('search_results', $results, ...)
Analysis of an apachesolr search request
   	 
           	 
                search_view()



        $response = $query->search(...)
$results = apachesolr_search_process_response
          ($response,$final_query)
                                   	 
   theme('search_results', $results, ...)
theme_apachesolr_search_snippets: sets the snippet
theme_apachesolr_search_snippets: sets the snippet




// Default implementation in apachesolr_search.module.
function theme_apachesolr_search_snippets($document, $snippets) {
  return implode(' ... ', $snippets) . ' ...';
}
theme_apachesolr_search_snippets: sets the snippet
theme_apachesolr_search_snippets: sets the snippet




// Custom implementation in template.php.
function mcgill_apachesolr_search_snippets($document, $snippets) {
  return 'anything you want!';
}
Analysis of an apachesolr search request
   	 
           	 
                search_view()



        $response = $query->search(...)
$results = apachesolr_search_process_response
          ($response,$final_query)
                                   	 
   theme('search_results', $results, ...)
search-result.tpl.php: renders a single search result



<?php print $result['node']->ss_course_code; ?>




If this is user input use check_plain() - Solr can
send you back the same (unsafe) user input you index.
See apachesolr_clean_text() if you want to index text
without tags.
Extra thanks to
     James McKinney
For use of his slides and for ideas.
jpmckinney on drupal.org
http://evolvingweb.ca/
http://cph2010.drupal.org/node/8168

More Related Content

What's hot

Solr Anti - patterns
Solr Anti - patternsSolr Anti - patterns
Solr Anti - patterns
Rafał Kuć
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes
Azim Kurt
 
Getting Creative with WordPress Queries, Again
Getting Creative with WordPress Queries, AgainGetting Creative with WordPress Queries, Again
Getting Creative with WordPress Queries, Again
DrewAPicture
 
[제1회 루씬 한글분석기 기술세미나] solr로 나만의 검색엔진을 만들어보자
[제1회 루씬 한글분석기 기술세미나] solr로 나만의 검색엔진을 만들어보자[제1회 루씬 한글분석기 기술세미나] solr로 나만의 검색엔진을 만들어보자
[제1회 루씬 한글분석기 기술세미나] solr로 나만의 검색엔진을 만들어보자
Donghyeok Kang
 
Hacking Your Way To Better Security
Hacking Your Way To Better SecurityHacking Your Way To Better Security
Hacking Your Way To Better Security
Colin O'Dell
 
Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016
Colin O'Dell
 
Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016
Colin O'Dell
 
Hacking Your Way To Better Security - php[tek] 2016
Hacking Your Way To Better Security - php[tek] 2016Hacking Your Way To Better Security - php[tek] 2016
Hacking Your Way To Better Security - php[tek] 2016
Colin O'Dell
 
Solr Anti-Patterns: Presented by Rafał Kuć, Sematext
Solr Anti-Patterns: Presented by Rafał Kuć, SematextSolr Anti-Patterns: Presented by Rafał Kuć, Sematext
Solr Anti-Patterns: Presented by Rafał Kuć, Sematext
Lucidworks
 
supporting t-sql scripts for Heap vs clustered table
supporting t-sql scripts for Heap vs clustered tablesupporting t-sql scripts for Heap vs clustered table
supporting t-sql scripts for Heap vs clustered table
Mahabubur Rahaman
 
Drupal is Stupid (But I Love It Anyway)
Drupal is Stupid (But I Love It Anyway)Drupal is Stupid (But I Love It Anyway)
Drupal is Stupid (But I Love It Anyway)
brockboland
 
Views notwithstanding
Views notwithstandingViews notwithstanding
Views notwithstanding
Srikanth Bangalore
 
UITableView Pain Points
UITableView Pain PointsUITableView Pain Points
UITableView Pain Points
Ken Auer
 
Your code sucks, let's fix it - PHP Master Series 2012
Your code sucks, let's fix it - PHP Master Series 2012Your code sucks, let's fix it - PHP Master Series 2012
Your code sucks, let's fix it - PHP Master Series 2012
Rafael Dohms
 
Drupal 8: Forms
Drupal 8: FormsDrupal 8: Forms
Drupal 8: Forms
drubb
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)
Fabien Potencier
 
CREATE INDEX … USING VODKA. VODKA CONNECTING INDEXES, Олег Бартунов, Александ...
CREATE INDEX … USING VODKA. VODKA CONNECTING INDEXES, Олег Бартунов, Александ...CREATE INDEX … USING VODKA. VODKA CONNECTING INDEXES, Олег Бартунов, Александ...
CREATE INDEX … USING VODKA. VODKA CONNECTING INDEXES, Олег Бартунов, Александ...
Ontico
 
Php (1)
Php (1)Php (1)
Php (1)
pinalsadiwala
 
Mysql query optimization
Mysql query optimizationMysql query optimization
Mysql query optimization
Baohua Cai
 

What's hot (19)

Solr Anti - patterns
Solr Anti - patternsSolr Anti - patterns
Solr Anti - patterns
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes
 
Getting Creative with WordPress Queries, Again
Getting Creative with WordPress Queries, AgainGetting Creative with WordPress Queries, Again
Getting Creative with WordPress Queries, Again
 
[제1회 루씬 한글분석기 기술세미나] solr로 나만의 검색엔진을 만들어보자
[제1회 루씬 한글분석기 기술세미나] solr로 나만의 검색엔진을 만들어보자[제1회 루씬 한글분석기 기술세미나] solr로 나만의 검색엔진을 만들어보자
[제1회 루씬 한글분석기 기술세미나] solr로 나만의 검색엔진을 만들어보자
 
Hacking Your Way To Better Security
Hacking Your Way To Better SecurityHacking Your Way To Better Security
Hacking Your Way To Better Security
 
Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016
 
Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016
 
Hacking Your Way To Better Security - php[tek] 2016
Hacking Your Way To Better Security - php[tek] 2016Hacking Your Way To Better Security - php[tek] 2016
Hacking Your Way To Better Security - php[tek] 2016
 
Solr Anti-Patterns: Presented by Rafał Kuć, Sematext
Solr Anti-Patterns: Presented by Rafał Kuć, SematextSolr Anti-Patterns: Presented by Rafał Kuć, Sematext
Solr Anti-Patterns: Presented by Rafał Kuć, Sematext
 
supporting t-sql scripts for Heap vs clustered table
supporting t-sql scripts for Heap vs clustered tablesupporting t-sql scripts for Heap vs clustered table
supporting t-sql scripts for Heap vs clustered table
 
Drupal is Stupid (But I Love It Anyway)
Drupal is Stupid (But I Love It Anyway)Drupal is Stupid (But I Love It Anyway)
Drupal is Stupid (But I Love It Anyway)
 
Views notwithstanding
Views notwithstandingViews notwithstanding
Views notwithstanding
 
UITableView Pain Points
UITableView Pain PointsUITableView Pain Points
UITableView Pain Points
 
Your code sucks, let's fix it - PHP Master Series 2012
Your code sucks, let's fix it - PHP Master Series 2012Your code sucks, let's fix it - PHP Master Series 2012
Your code sucks, let's fix it - PHP Master Series 2012
 
Drupal 8: Forms
Drupal 8: FormsDrupal 8: Forms
Drupal 8: Forms
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)
 
CREATE INDEX … USING VODKA. VODKA CONNECTING INDEXES, Олег Бартунов, Александ...
CREATE INDEX … USING VODKA. VODKA CONNECTING INDEXES, Олег Бартунов, Александ...CREATE INDEX … USING VODKA. VODKA CONNECTING INDEXES, Олег Бартунов, Александ...
CREATE INDEX … USING VODKA. VODKA CONNECTING INDEXES, Олег Бартунов, Александ...
 
Php (1)
Php (1)Php (1)
Php (1)
 
Mysql query optimization
Mysql query optimizationMysql query optimization
Mysql query optimization
 

Viewers also liked

Southern%20Honduras%20Vulnerability%20Assessment%20Report_CLEARED
Southern%20Honduras%20Vulnerability%20Assessment%20Report_CLEAREDSouthern%20Honduras%20Vulnerability%20Assessment%20Report_CLEARED
Southern%20Honduras%20Vulnerability%20Assessment%20Report_CLEARED
Luis Caballero Bonilla
 
Francy lorena mancholacruz_actividad1_2mapac
Francy lorena mancholacruz_actividad1_2mapacFrancy lorena mancholacruz_actividad1_2mapac
Francy lorena mancholacruz_actividad1_2mapac
lorena cruz
 
Plano l11638
Plano l11638Plano l11638
Plano l11638
Dennis Neves
 
Elementary & Auxiliary Strategies Imparting Smartness to a city
Elementary & Auxiliary Strategies Imparting Smartness to a cityElementary & Auxiliary Strategies Imparting Smartness to a city
Elementary & Auxiliary Strategies Imparting Smartness to a city
Antara Nandy
 
From Activiti to camunda fox: The SaaS Scenario
From Activiti to camunda fox: The SaaS ScenarioFrom Activiti to camunda fox: The SaaS Scenario
From Activiti to camunda fox: The SaaS Scenario
Sven Jörges
 
Power point cam
Power point camPower point cam
Power point cam
MARIA SECADES CUESTA
 
Sprinklr vs Salesforce
Sprinklr vs SalesforceSprinklr vs Salesforce
Sprinklr vs Salesforce
Empire Selling
 
WE HATE CUSTOMERS
WE HATE CUSTOMERSWE HATE CUSTOMERS
WE HATE CUSTOMERS
Laimonas Burneckis
 
Real-Life-BPM mit Java EE: Ein Erfahrungsbericht
Real-Life-BPM mit Java EE: Ein ErfahrungsberichtReal-Life-BPM mit Java EE: Ein Erfahrungsbericht
Real-Life-BPM mit Java EE: Ein Erfahrungsbericht
Sven Jörges
 
Gestión y control de calidad
Gestión y control de calidadGestión y control de calidad
Gestión y control de calidad
Raúl Cordova
 
Activiti: a developer-friendly process engine
Activiti: a developer-friendly process engineActiviti: a developer-friendly process engine
Activiti: a developer-friendly process engine
Travis Carlson
 
Επαναληπτικό φύλλο εργασίας,, β γυμν Αρχαία, ενότ 1-5
Επαναληπτικό φύλλο εργασίας,, β γυμν Αρχαία, ενότ 1-5Επαναληπτικό φύλλο εργασίας,, β γυμν Αρχαία, ενότ 1-5
Επαναληπτικό φύλλο εργασίας,, β γυμν Αρχαία, ενότ 1-5
chavalesnick
 
Φύλλο εργασίας αρχαια Α΄ γυμν 11 ενοτ
Φύλλο εργασίας αρχαια Α΄ γυμν 11 ενοτΦύλλο εργασίας αρχαια Α΄ γυμν 11 ενοτ
Φύλλο εργασίας αρχαια Α΄ γυμν 11 ενοτ
chavalesnick
 

Viewers also liked (13)

Southern%20Honduras%20Vulnerability%20Assessment%20Report_CLEARED
Southern%20Honduras%20Vulnerability%20Assessment%20Report_CLEAREDSouthern%20Honduras%20Vulnerability%20Assessment%20Report_CLEARED
Southern%20Honduras%20Vulnerability%20Assessment%20Report_CLEARED
 
Francy lorena mancholacruz_actividad1_2mapac
Francy lorena mancholacruz_actividad1_2mapacFrancy lorena mancholacruz_actividad1_2mapac
Francy lorena mancholacruz_actividad1_2mapac
 
Plano l11638
Plano l11638Plano l11638
Plano l11638
 
Elementary & Auxiliary Strategies Imparting Smartness to a city
Elementary & Auxiliary Strategies Imparting Smartness to a cityElementary & Auxiliary Strategies Imparting Smartness to a city
Elementary & Auxiliary Strategies Imparting Smartness to a city
 
From Activiti to camunda fox: The SaaS Scenario
From Activiti to camunda fox: The SaaS ScenarioFrom Activiti to camunda fox: The SaaS Scenario
From Activiti to camunda fox: The SaaS Scenario
 
Power point cam
Power point camPower point cam
Power point cam
 
Sprinklr vs Salesforce
Sprinklr vs SalesforceSprinklr vs Salesforce
Sprinklr vs Salesforce
 
WE HATE CUSTOMERS
WE HATE CUSTOMERSWE HATE CUSTOMERS
WE HATE CUSTOMERS
 
Real-Life-BPM mit Java EE: Ein Erfahrungsbericht
Real-Life-BPM mit Java EE: Ein ErfahrungsberichtReal-Life-BPM mit Java EE: Ein Erfahrungsbericht
Real-Life-BPM mit Java EE: Ein Erfahrungsbericht
 
Gestión y control de calidad
Gestión y control de calidadGestión y control de calidad
Gestión y control de calidad
 
Activiti: a developer-friendly process engine
Activiti: a developer-friendly process engineActiviti: a developer-friendly process engine
Activiti: a developer-friendly process engine
 
Επαναληπτικό φύλλο εργασίας,, β γυμν Αρχαία, ενότ 1-5
Επαναληπτικό φύλλο εργασίας,, β γυμν Αρχαία, ενότ 1-5Επαναληπτικό φύλλο εργασίας,, β γυμν Αρχαία, ενότ 1-5
Επαναληπτικό φύλλο εργασίας,, β γυμν Αρχαία, ενότ 1-5
 
Φύλλο εργασίας αρχαια Α΄ γυμν 11 ενοτ
Φύλλο εργασίας αρχαια Α΄ γυμν 11 ενοτΦύλλο εργασίας αρχαια Α΄ γυμν 11 ενοτ
Φύλλο εργασίας αρχαια Α΄ γυμν 11 ενοτ
 

Similar to Apache Solr Search Mastery

Eric Redmond – Distributed Search on Riak 2.0 - NoSQL matters Barcelona 2014
Eric Redmond – Distributed Search on Riak 2.0 - NoSQL matters Barcelona 2014Eric Redmond – Distributed Search on Riak 2.0 - NoSQL matters Barcelona 2014
Eric Redmond – Distributed Search on Riak 2.0 - NoSQL matters Barcelona 2014
NoSQLmatters
 
Drupal7 dbtng
Drupal7  dbtngDrupal7  dbtng
Drupal7 dbtng
Nicolas Leroy
 
Cassandra summit
Cassandra summitCassandra summit
Cassandra summit
mattstump
 
dcs plus Catalogue 2015
dcs plus Catalogue 2015dcs plus Catalogue 2015
dcs plus Catalogue 2015
dcs plus
 
Tutorial, Part 3: SharePoint 101: Jump-Starting the Developer by Rob Windsor ...
Tutorial, Part 3: SharePoint 101: Jump-Starting the Developer by Rob Windsor ...Tutorial, Part 3: SharePoint 101: Jump-Starting the Developer by Rob Windsor ...
Tutorial, Part 3: SharePoint 101: Jump-Starting the Developer by Rob Windsor ...
SPTechCon
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
elliando dias
 
Resource Routing in ExpressionEngine
Resource Routing in ExpressionEngineResource Routing in ExpressionEngine
Resource Routing in ExpressionEngine
MichaelRog
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
Kris Wallsmith
 
The State of Lithium
The State of LithiumThe State of Lithium
The State of Lithium
Nate Abele
 
Broadleaf Presents Thymeleaf
Broadleaf Presents ThymeleafBroadleaf Presents Thymeleaf
Broadleaf Presents Thymeleaf
Broadleaf Commerce
 
Php
PhpPhp
Solr integration in Magento Enterprise
Solr integration in Magento EnterpriseSolr integration in Magento Enterprise
Solr integration in Magento Enterprise
Tobias Zander
 
Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)
Jeff Eaton
 
Nickolay Shmalenuk.Render api eng.DrupalCamp Kyiv 2011
Nickolay Shmalenuk.Render api eng.DrupalCamp Kyiv 2011Nickolay Shmalenuk.Render api eng.DrupalCamp Kyiv 2011
Nickolay Shmalenuk.Render api eng.DrupalCamp Kyiv 2011
camp_drupal_ua
 
第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource
Kaz Watanabe
 
Solr Anti Patterns
Solr Anti PatternsSolr Anti Patterns
Solr Anti Patterns
Sematext Group, Inc.
 
21. CodeIgniter search
21. CodeIgniter search21. CodeIgniter search
21. CodeIgniter search
Razvan Raducanu, PhD
 
Elasticsearch and Symfony Integration - Debarko De
Elasticsearch and Symfony Integration - Debarko DeElasticsearch and Symfony Integration - Debarko De
Elasticsearch and Symfony Integration - Debarko De
Debarko De
 
DrupalCamp Foz - Novas APIs Drupal 7
DrupalCamp Foz - Novas APIs Drupal 7DrupalCamp Foz - Novas APIs Drupal 7
DrupalCamp Foz - Novas APIs Drupal 7
chuvainc
 
Why Hacking WordPress Search Isn't Some Big Scary Thing
Why Hacking WordPress Search Isn't Some Big Scary ThingWhy Hacking WordPress Search Isn't Some Big Scary Thing
Why Hacking WordPress Search Isn't Some Big Scary Thing
Chris Reynolds
 

Similar to Apache Solr Search Mastery (20)

Eric Redmond – Distributed Search on Riak 2.0 - NoSQL matters Barcelona 2014
Eric Redmond – Distributed Search on Riak 2.0 - NoSQL matters Barcelona 2014Eric Redmond – Distributed Search on Riak 2.0 - NoSQL matters Barcelona 2014
Eric Redmond – Distributed Search on Riak 2.0 - NoSQL matters Barcelona 2014
 
Drupal7 dbtng
Drupal7  dbtngDrupal7  dbtng
Drupal7 dbtng
 
Cassandra summit
Cassandra summitCassandra summit
Cassandra summit
 
dcs plus Catalogue 2015
dcs plus Catalogue 2015dcs plus Catalogue 2015
dcs plus Catalogue 2015
 
Tutorial, Part 3: SharePoint 101: Jump-Starting the Developer by Rob Windsor ...
Tutorial, Part 3: SharePoint 101: Jump-Starting the Developer by Rob Windsor ...Tutorial, Part 3: SharePoint 101: Jump-Starting the Developer by Rob Windsor ...
Tutorial, Part 3: SharePoint 101: Jump-Starting the Developer by Rob Windsor ...
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
 
Resource Routing in ExpressionEngine
Resource Routing in ExpressionEngineResource Routing in ExpressionEngine
Resource Routing in ExpressionEngine
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
The State of Lithium
The State of LithiumThe State of Lithium
The State of Lithium
 
Broadleaf Presents Thymeleaf
Broadleaf Presents ThymeleafBroadleaf Presents Thymeleaf
Broadleaf Presents Thymeleaf
 
Php
PhpPhp
Php
 
Solr integration in Magento Enterprise
Solr integration in Magento EnterpriseSolr integration in Magento Enterprise
Solr integration in Magento Enterprise
 
Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)
 
Nickolay Shmalenuk.Render api eng.DrupalCamp Kyiv 2011
Nickolay Shmalenuk.Render api eng.DrupalCamp Kyiv 2011Nickolay Shmalenuk.Render api eng.DrupalCamp Kyiv 2011
Nickolay Shmalenuk.Render api eng.DrupalCamp Kyiv 2011
 
第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource
 
Solr Anti Patterns
Solr Anti PatternsSolr Anti Patterns
Solr Anti Patterns
 
21. CodeIgniter search
21. CodeIgniter search21. CodeIgniter search
21. CodeIgniter search
 
Elasticsearch and Symfony Integration - Debarko De
Elasticsearch and Symfony Integration - Debarko DeElasticsearch and Symfony Integration - Debarko De
Elasticsearch and Symfony Integration - Debarko De
 
DrupalCamp Foz - Novas APIs Drupal 7
DrupalCamp Foz - Novas APIs Drupal 7DrupalCamp Foz - Novas APIs Drupal 7
DrupalCamp Foz - Novas APIs Drupal 7
 
Why Hacking WordPress Search Isn't Some Big Scary Thing
Why Hacking WordPress Search Isn't Some Big Scary ThingWhy Hacking WordPress Search Isn't Some Big Scary Thing
Why Hacking WordPress Search Isn't Some Big Scary Thing
 

More from Acquia

Acquia_Adcetera Webinar_Marketing Automation.pdf
Acquia_Adcetera Webinar_Marketing Automation.pdfAcquia_Adcetera Webinar_Marketing Automation.pdf
Acquia_Adcetera Webinar_Marketing Automation.pdf
Acquia
 
Acquia Webinar Deck - 9_13 .pdf
Acquia Webinar Deck - 9_13 .pdfAcquia Webinar Deck - 9_13 .pdf
Acquia Webinar Deck - 9_13 .pdf
Acquia
 
Taking Your Multi-Site Management at Scale to the Next Level
Taking Your Multi-Site Management at Scale to the Next LevelTaking Your Multi-Site Management at Scale to the Next Level
Taking Your Multi-Site Management at Scale to the Next Level
Acquia
 
CDP for Retail Webinar with Appnovation - Q2 2022.pdf
CDP for Retail Webinar with Appnovation - Q2 2022.pdfCDP for Retail Webinar with Appnovation - Q2 2022.pdf
CDP for Retail Webinar with Appnovation - Q2 2022.pdf
Acquia
 
May Partner Bootcamp 2022
May Partner Bootcamp 2022May Partner Bootcamp 2022
May Partner Bootcamp 2022
Acquia
 
April Partner Bootcamp 2022
April Partner Bootcamp 2022April Partner Bootcamp 2022
April Partner Bootcamp 2022
Acquia
 
How to Unify Brand Experience: A Hootsuite Story
How to Unify Brand Experience: A Hootsuite Story How to Unify Brand Experience: A Hootsuite Story
How to Unify Brand Experience: A Hootsuite Story
Acquia
 
Using Personas to Guide DAM Results: How Life Time Pumped Up Their UX and CX
Using Personas to Guide DAM Results: How Life Time Pumped Up Their UX and CXUsing Personas to Guide DAM Results: How Life Time Pumped Up Their UX and CX
Using Personas to Guide DAM Results: How Life Time Pumped Up Their UX and CX
Acquia
 
Improve Code Quality and Time to Market: 100% Cloud-Based Development Workflow
Improve Code Quality and Time to Market: 100% Cloud-Based Development WorkflowImprove Code Quality and Time to Market: 100% Cloud-Based Development Workflow
Improve Code Quality and Time to Market: 100% Cloud-Based Development Workflow
Acquia
 
September Partner Bootcamp
September Partner BootcampSeptember Partner Bootcamp
September Partner Bootcamp
Acquia
 
August partner bootcamp
August partner bootcampAugust partner bootcamp
August partner bootcamp
Acquia
 
July 2021 Partner Bootcamp
July  2021 Partner BootcampJuly  2021 Partner Bootcamp
July 2021 Partner Bootcamp
Acquia
 
May Partner Bootcamp
May Partner BootcampMay Partner Bootcamp
May Partner Bootcamp
Acquia
 
DRUPAL 7 END OF LIFE IS NEAR - MIGRATE TO DRUPAL 9 FAST AND EASY
DRUPAL 7 END OF LIFE IS NEAR - MIGRATE TO DRUPAL 9 FAST AND EASYDRUPAL 7 END OF LIFE IS NEAR - MIGRATE TO DRUPAL 9 FAST AND EASY
DRUPAL 7 END OF LIFE IS NEAR - MIGRATE TO DRUPAL 9 FAST AND EASY
Acquia
 
Work While You Sleep: The CMO’s Guide to a 24/7/365 Lead Machine
Work While You Sleep: The CMO’s Guide to a 24/7/365 Lead MachineWork While You Sleep: The CMO’s Guide to a 24/7/365 Lead Machine
Work While You Sleep: The CMO’s Guide to a 24/7/365 Lead Machine
Acquia
 
Acquia webinar: Leveraging Drupal to Bury Your Sales Team In B2B Leads
Acquia webinar: Leveraging Drupal to Bury Your Sales Team In B2B LeadsAcquia webinar: Leveraging Drupal to Bury Your Sales Team In B2B Leads
Acquia webinar: Leveraging Drupal to Bury Your Sales Team In B2B Leads
Acquia
 
April partner bootcamp deck cookieless future
April partner bootcamp deck  cookieless futureApril partner bootcamp deck  cookieless future
April partner bootcamp deck cookieless future
Acquia
 
How to enhance cx through personalised, automated solutions
How to enhance cx through personalised, automated solutionsHow to enhance cx through personalised, automated solutions
How to enhance cx through personalised, automated solutions
Acquia
 
DRUPAL MIGRATIONS AND DRUPAL 9 INNOVATION: HOW PAC-12 DELIVERED DIGITALLY FOR...
DRUPAL MIGRATIONS AND DRUPAL 9 INNOVATION: HOW PAC-12 DELIVERED DIGITALLY FOR...DRUPAL MIGRATIONS AND DRUPAL 9 INNOVATION: HOW PAC-12 DELIVERED DIGITALLY FOR...
DRUPAL MIGRATIONS AND DRUPAL 9 INNOVATION: HOW PAC-12 DELIVERED DIGITALLY FOR...
Acquia
 
Customer Experience (CX): 3 Key Factors Shaping CX Redesign in 2021
Customer Experience (CX): 3 Key Factors Shaping CX Redesign in 2021Customer Experience (CX): 3 Key Factors Shaping CX Redesign in 2021
Customer Experience (CX): 3 Key Factors Shaping CX Redesign in 2021
Acquia
 

More from Acquia (20)

Acquia_Adcetera Webinar_Marketing Automation.pdf
Acquia_Adcetera Webinar_Marketing Automation.pdfAcquia_Adcetera Webinar_Marketing Automation.pdf
Acquia_Adcetera Webinar_Marketing Automation.pdf
 
Acquia Webinar Deck - 9_13 .pdf
Acquia Webinar Deck - 9_13 .pdfAcquia Webinar Deck - 9_13 .pdf
Acquia Webinar Deck - 9_13 .pdf
 
Taking Your Multi-Site Management at Scale to the Next Level
Taking Your Multi-Site Management at Scale to the Next LevelTaking Your Multi-Site Management at Scale to the Next Level
Taking Your Multi-Site Management at Scale to the Next Level
 
CDP for Retail Webinar with Appnovation - Q2 2022.pdf
CDP for Retail Webinar with Appnovation - Q2 2022.pdfCDP for Retail Webinar with Appnovation - Q2 2022.pdf
CDP for Retail Webinar with Appnovation - Q2 2022.pdf
 
May Partner Bootcamp 2022
May Partner Bootcamp 2022May Partner Bootcamp 2022
May Partner Bootcamp 2022
 
April Partner Bootcamp 2022
April Partner Bootcamp 2022April Partner Bootcamp 2022
April Partner Bootcamp 2022
 
How to Unify Brand Experience: A Hootsuite Story
How to Unify Brand Experience: A Hootsuite Story How to Unify Brand Experience: A Hootsuite Story
How to Unify Brand Experience: A Hootsuite Story
 
Using Personas to Guide DAM Results: How Life Time Pumped Up Their UX and CX
Using Personas to Guide DAM Results: How Life Time Pumped Up Their UX and CXUsing Personas to Guide DAM Results: How Life Time Pumped Up Their UX and CX
Using Personas to Guide DAM Results: How Life Time Pumped Up Their UX and CX
 
Improve Code Quality and Time to Market: 100% Cloud-Based Development Workflow
Improve Code Quality and Time to Market: 100% Cloud-Based Development WorkflowImprove Code Quality and Time to Market: 100% Cloud-Based Development Workflow
Improve Code Quality and Time to Market: 100% Cloud-Based Development Workflow
 
September Partner Bootcamp
September Partner BootcampSeptember Partner Bootcamp
September Partner Bootcamp
 
August partner bootcamp
August partner bootcampAugust partner bootcamp
August partner bootcamp
 
July 2021 Partner Bootcamp
July  2021 Partner BootcampJuly  2021 Partner Bootcamp
July 2021 Partner Bootcamp
 
May Partner Bootcamp
May Partner BootcampMay Partner Bootcamp
May Partner Bootcamp
 
DRUPAL 7 END OF LIFE IS NEAR - MIGRATE TO DRUPAL 9 FAST AND EASY
DRUPAL 7 END OF LIFE IS NEAR - MIGRATE TO DRUPAL 9 FAST AND EASYDRUPAL 7 END OF LIFE IS NEAR - MIGRATE TO DRUPAL 9 FAST AND EASY
DRUPAL 7 END OF LIFE IS NEAR - MIGRATE TO DRUPAL 9 FAST AND EASY
 
Work While You Sleep: The CMO’s Guide to a 24/7/365 Lead Machine
Work While You Sleep: The CMO’s Guide to a 24/7/365 Lead MachineWork While You Sleep: The CMO’s Guide to a 24/7/365 Lead Machine
Work While You Sleep: The CMO’s Guide to a 24/7/365 Lead Machine
 
Acquia webinar: Leveraging Drupal to Bury Your Sales Team In B2B Leads
Acquia webinar: Leveraging Drupal to Bury Your Sales Team In B2B LeadsAcquia webinar: Leveraging Drupal to Bury Your Sales Team In B2B Leads
Acquia webinar: Leveraging Drupal to Bury Your Sales Team In B2B Leads
 
April partner bootcamp deck cookieless future
April partner bootcamp deck  cookieless futureApril partner bootcamp deck  cookieless future
April partner bootcamp deck cookieless future
 
How to enhance cx through personalised, automated solutions
How to enhance cx through personalised, automated solutionsHow to enhance cx through personalised, automated solutions
How to enhance cx through personalised, automated solutions
 
DRUPAL MIGRATIONS AND DRUPAL 9 INNOVATION: HOW PAC-12 DELIVERED DIGITALLY FOR...
DRUPAL MIGRATIONS AND DRUPAL 9 INNOVATION: HOW PAC-12 DELIVERED DIGITALLY FOR...DRUPAL MIGRATIONS AND DRUPAL 9 INNOVATION: HOW PAC-12 DELIVERED DIGITALLY FOR...
DRUPAL MIGRATIONS AND DRUPAL 9 INNOVATION: HOW PAC-12 DELIVERED DIGITALLY FOR...
 
Customer Experience (CX): 3 Key Factors Shaping CX Redesign in 2021
Customer Experience (CX): 3 Key Factors Shaping CX Redesign in 2021Customer Experience (CX): 3 Key Factors Shaping CX Redesign in 2021
Customer Experience (CX): 3 Key Factors Shaping CX Redesign in 2021
 

Recently uploaded

GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
Tomaz Bratanic
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
kumardaparthi1024
 
UI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentationUI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentation
Wouter Lemaire
 
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Tatiana Kojar
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
MichaelKnudsen27
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
Chart Kalyan
 
Introduction of Cybersecurity with OSS at Code Europe 2024
Introduction of Cybersecurity with OSS  at Code Europe 2024Introduction of Cybersecurity with OSS  at Code Europe 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
Hiroshi SHIBATA
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Safe Software
 
Nunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdf
Nunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdfNunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdf
Nunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdf
flufftailshop
 
June Patch Tuesday
June Patch TuesdayJune Patch Tuesday
June Patch Tuesday
Ivanti
 
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - HiikeSystem Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
Hiike
 
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development ProvidersYour One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
akankshawande
 
Trusted Execution Environment for Decentralized Process Mining
Trusted Execution Environment for Decentralized Process MiningTrusted Execution Environment for Decentralized Process Mining
Trusted Execution Environment for Decentralized Process Mining
LucaBarbaro3
 
Letter and Document Automation for Bonterra Impact Management (fka Social Sol...
Letter and Document Automation for Bonterra Impact Management (fka Social Sol...Letter and Document Automation for Bonterra Impact Management (fka Social Sol...
Letter and Document Automation for Bonterra Impact Management (fka Social Sol...
Jeffrey Haguewood
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
Zilliz
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc
 
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdfMonitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Tosin Akinosho
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
innovationoecd
 
Recommendation System using RAG Architecture
Recommendation System using RAG ArchitectureRecommendation System using RAG Architecture
Recommendation System using RAG Architecture
fredae14
 
Finale of the Year: Apply for Next One!
Finale of the Year: Apply for Next One!Finale of the Year: Apply for Next One!
Finale of the Year: Apply for Next One!
GDSC PJATK
 

Recently uploaded (20)

GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
 
UI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentationUI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentation
 
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
 
Introduction of Cybersecurity with OSS at Code Europe 2024
Introduction of Cybersecurity with OSS  at Code Europe 2024Introduction of Cybersecurity with OSS  at Code Europe 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
 
Nunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdf
Nunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdfNunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdf
Nunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdf
 
June Patch Tuesday
June Patch TuesdayJune Patch Tuesday
June Patch Tuesday
 
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - HiikeSystem Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
 
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development ProvidersYour One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
 
Trusted Execution Environment for Decentralized Process Mining
Trusted Execution Environment for Decentralized Process MiningTrusted Execution Environment for Decentralized Process Mining
Trusted Execution Environment for Decentralized Process Mining
 
Letter and Document Automation for Bonterra Impact Management (fka Social Sol...
Letter and Document Automation for Bonterra Impact Management (fka Social Sol...Letter and Document Automation for Bonterra Impact Management (fka Social Sol...
Letter and Document Automation for Bonterra Impact Management (fka Social Sol...
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
 
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdfMonitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdf
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
 
Recommendation System using RAG Architecture
Recommendation System using RAG ArchitectureRecommendation System using RAG Architecture
Recommendation System using RAG Architecture
 
Finale of the Year: Apply for Next One!
Finale of the Year: Apply for Next One!Finale of the Year: Apply for Next One!
Finale of the Year: Apply for Next One!
 

Apache Solr Search Mastery

  • 1. Apache Solr Search Mastery Peter Wolanin and Robert Douglass 25. aug 13:30 Trellon
  • 2. We  hope  you  will  leave  having   learned  about: • What  is  Solr  and  how  do  you  run  it  locally • Ge9ng  Drupal  data  into  Solr • Changes  in  Drupal  7 • Field  API  integraAon • Searching  Solr  from  Drupal • Modifying  what’s  searched  and  the  results • Theming  search  results
  • 3. Drupal  Interacts  with  Solr  via  HTTP • Drupal  sends  data  to  Solr  as  XML  documents • Solr  accepts  documents  POSTed  to  /update • A  different  XML  can  be  POSTed  to  delete • Searching,  etc  are  GET  requests • If  something  is  not  working  as  expected,  you   can  try  searching  directly  in  Solr  via  URL • Solr  also  includes  admin  and  analysis  interfaces   (you  need  to  lock  this  down  for  producAon).
  • 4. Run  Solr  Using  the  Example  Dir Replace the schema.xml and solrconfig.xml with the ones from the Drupal module Invoke the start.jar: java -jar start.jar
  • 5.
  • 6. Schema:  Defines  Types  &  Fields <?xml version="1.0" encoding="UTF-8" ?> <schema name="drupal-0.9.5" version="1.2"> <types> ... </types> <fields> <!-- The document id is derived from a site-spcific key (hash) and the node ID like: $document->id = $hash . '/node/' . $node->nid; --> <field name="id" type="string" indexed="true" stored="true" required="true" /> <!-- These are the fields that correspond to a Drupal node. --> <field name="site" type="string" indexed="true" stored="true"/> <field name="hash" type="string" indexed="true" stored="true"/> <field name="url" type="string" indexed="true" stored="true"/> <field name="title" type="text" indexed="true" stored="true" termVectors="true" omitNorms="true"/> <field name="sort_title" type="sortString" indexed="true" stored="false"/> <field name="body" type="text" indexed="true" stored="true" termVectors="true"/> <field name="teaser" type="text" indexed="false" stored="true"/> ... </fields> <uniqueKey>id</uniqueKey> <!-- field for the QueryParser to use when an explicit fieldname is absent --> <defaultSearchField>body</defaultSearchField> <!-- SolrQueryParser configuration: defaultOperator="AND|OR" --> <solrQueryParser defaultOperator="AND"/> </schema>
  • 7. Schema:  Defines  Types  &  Fields <field name="id" type="string" indexed="true" stored="true" required="true" /> <!-- These are the fields that correspond to a Drupal node. --> <field name="site" type="string" indexed="true" stored="true"/> <field name="hash" type="string" indexed="true" stored="true"/>
  • 8. Dynamic  Fields  Provide  Flexibility <!-- Dynamic field definitions will be used if the name matches any of the patterns. The glob-like pattern in the name attribute must have "*" only at the start or the end. Longer patterns will be matched first. --> <dynamicField name="is_*" type="integer" indexed="true" stored="true" multiValued="false"/> <dynamicField name="im_*" type="integer" indexed="true" stored="true" multiValued="true"/> ... <dynamicField name="ss_*" type="string" indexed="true" stored="true" multiValued="false"/> <dynamicField name="ts_*" type="text" indexed="true" stored="true" multiValued="false" termVectors="true"/> <dynamicField name="ds_*" type="date" indexed="true" stored="true" multiValued="false"/> <dynamicField name="dm_*" type="date" indexed="true" stored="true" multiValued="true"/> <dynamicField name="tds_*" type="tdate"indexed="true" stored="true" multiValued="false"/> <dynamicField name="tdm_*" type="tdate"indexed="true" stored="true" multiValued="true"/> <dynamicField name="bm_*" type="boolean" indexed="true" stored="true" multiValued="true"/> <dynamicField name="bs_*" type="boolean" indexed="true" stored="true" multiValued="false"/> ... <!-- Sortable version of the dynamic string field --> <dynamicField name="sort_ss_*" type="sortString" indexed="true" stored="false"/> <copyField source="ss_*" dest="sort_ss_*"/> <!-- A random sort field --> <dynamicField name="random_*" type="rand" indexed="true" stored="true"/> <!-- This field is used to store node access records, as opposed to CCK field data --> <dynamicField name="nodeaccess*" type="integer" indexed="true" stored="false" multiValued="true"/> <dynamicField name="*" type="ignored" multiValued="true" />
  • 9. Dynamic  Fields  Provide  Flexibility <!-- Dynamic field definitions will be used if the name matches any of the patterns. The glob-like pattern in the name attribute must have "*" only at the start or the end. Longer patterns will be matched first. --> <dynamicField name="is_*" type="integer" indexed="true" stored="true" multiValued="false"/> <dynamicField name="im_*" type="integer" indexed="true" stored="true" multiValued="true"/>
  • 10. Dynamic  Fields  Provide  Flexibility <!-- Dynamic field definitions will be used if the name matches any of the patterns. The glob-like pattern in the name attribute must have "*" only at the start or the end. Longer patterns will be matched first. --> <dynamicField name="is_*" type="integer" indexed="true" stored="true" multiValued="false"/> <dynamicField name="im_*" type="integer" indexed="true" stored="true" multiValued="true"/> ... <dynamicField name="ss_*" type="string" indexed="true" stored="true" multiValued="false"/> <dynamicField name="ts_*" type="text" indexed="true" stored="true" multiValued="false" termVectors="true"/> <dynamicField name="ds_*" type="date" indexed="true" stored="true" multiValued="false"/> <dynamicField name="dm_*" type="date" indexed="true" stored="true" multiValued="true"/> <dynamicField name="tds_*" type="tdate"indexed="true" stored="true" multiValued="false"/> <dynamicField name="tdm_*" type="tdate"indexed="true" stored="true" multiValued="true"/> <dynamicField name="bm_*" type="boolean" indexed="true" stored="true" multiValued="true"/> <dynamicField name="bs_*" type="boolean" indexed="true" stored="true" multiValued="false"/> ... <!-- Sortable version of the dynamic string field --> <dynamicField name="sort_ss_*" type="sortString" indexed="true" stored="false"/> <copyField source="ss_*" dest="sort_ss_*"/> <!-- A random sort field --> <dynamicField name="random_*" type="rand" indexed="true" stored="true"/> <!-- This field is used to store node access records, as opposed to CCK field data --> <dynamicField name="nodeaccess*" type="integer" indexed="true" stored="false" multiValued="true"/> <dynamicField name="*" type="ignored" multiValued="true" />
  • 11. Dynamic  Fields  Provide  Flexibility <!-- Sortable version of the dynamic string field --> <dynamicField name="sort_ss_*" type="sortString" indexed="true" stored="false"/> <copyField source="ss_*" dest="sort_ss_*"/> <!-- This field is used to store node access records, as opposed to CCK field data --> <dynamicField name="nodeaccess*" type="integer" indexed="true" stored="false" multiValued="true"/> <dynamicField name="*" type="ignored" multiValued="true" />
  • 13. Use the factory method to get an object for building your queries: $query = apachesolr_drupal_query( $keys = '', $filters = '', $solrsort = '', $base_path = '', $solr = NULL );
  • 14. The actual class that is returned is determined by a Drupal variable: variable_get('apachesolr_query_class', array('apachesolr', 'Solr_Base_Query'));
  • 15. interface Drupal_Solr_Query_Interface { get_filters($name); has_filter($field, $value); add_filter($field, $value, $exclude); remove_filter($field, $value); ... }
  • 16. interface Drupal_Solr_Query_Interface { ... get_keys(); set_keys($keys); remove_keys(); ... }
  • 17. interface Drupal_Solr_Query_Interface { ... get_path(); get_url_queryvalues(); get_query_basic(); ... }
  • 18. interface Drupal_Solr_Query_Interface { ... get_available_sorts(); set_available_sort($field, $sort); get_solrsort(); set_solrsort($field, $direction); ... }
  • 19. interface Drupal_Solr_Query_Interface { ... add_subquery( Drupal_Solr_Query_Interface $query); remove_subquery( Drupal_Solr_Query_Interface $query); remove_subqueries(); ... }
  • 20. interface Drupal_Solr_Query_Interface { ... // Passes to the $solr object which // executes the search. search($keys = NULL); }
  • 22. Use the factory method to get an object for sending requests to Solr: $solr = apachesolr_get_solr($host, $port, $path);
  • 23. The actual class that is returned is determined by a Drupal variable: variable_get('apachesolr_service_class', array('apachesolr', 'Drupal_Apache_Solr_Service.php', 'Drupal_Apache_Solr_Service') );
  • 24. This allows you to customize the way search works by providing a different solr service class than the standard. variable_set('apachesolr_service_class', array('acquia_search', 'Acquia_Search_Service.php', 'Acquia_Search_Service') );
  • 25. http://code.google.com/p/solr-php-client/ class Apache_Solr_Service { addDocument( Apache_Solr_Document $document); addDocuments($documents); deleteById($id); deleteByQuery($rawQuery); ... }
  • 28. class Drupal_Apache_Solr_Service extends Apache_Solr_Service { getLuke(); getFields(); getStatsSummary(); ... }
  • 29. class Drupal_Apache_Solr_Service extends Apache_Solr_Service { // Takes control of the request sending // and headers - Drupal idiomatic. _makeHttpRequest(); }
  • 31. http://code.google.com/p/solr-php-client/ class Apache_Solr_Document { addField($key, $value, $boost); setMultiValue($key, $value, $boost); }
  • 32. Drupal  7  Changes   $query, $params $query->params $solr->search() $query->search() • Taxonomy  on  a  node  is  now  a  term  reference  field   (works  as  part  of  the  Field  API  integraAon). • Fixes  to  core  search  module  APIs  mean  that  some   hacks  are  gone:  e.g.  no,  hook_menu_alter;  we   can  set  apachesolr  as  the  default  via  search  UI.
  • 33. You  Can  Add  Any  Data  to  the  Index hook_apachesolr_update_index(&$document, $node, $namespace) • Used  to  add  more  data  to  a  document  before   it’s  sent  to  Solr. • Can  also  be  used  to  alter  or  replace  data  added   by  apachesolr  or  another  module. • This  is  it!  (it  works  like  an  _alter  hook).
  • 34. Image  Data  Using  Dynamic  Fields /** * Implementation of hook_apachesolr_update_index(). */ function apachesolr_image_apachesolr_update_index(&$document, $node, $namespace) { if ($node->type == 'image' && $document->entity == 'node') { $areas = array(); $sizes = image_get_derivative_sizes($node->images['_original']); foreach ($sizes as $name => $info) { $areas[$name] = $info['width'] * $info['height']; } asort($areas); $image_path = FALSE; foreach ($areas as $preset => $size) { $image_path = $node->images[$preset]; break; } if ($image_path) { $document->ss_image_relative = $image_path; // Support multi-site too. $document->ss_image_absolute = file_create_url($image_path); } } } /** * Implementation of hook_apachesolr_modify_query(). */ function apachesolr_image_apachesolr_modify_query($query, $caller) { // Also retrieve image thumbnail links. $query->params['fl'] .= ',ss_image_relative'; }
  • 35. Image  Data  Using  Dynamic  Fields if ($image_path) { $document->ss_image_relative = $image_path; } /** * Implement hook_apachesolr_modify_query(). */ function apachesolr_image_apachesolr_modify_query( $query, $caller) { // Also retrieve image thumbnail links. $query->params['fl'] .= ',ss_image_relative'; }
  • 36. UI  to  Exclude  Whole  Content  Types • ?q=admin/config/search/apachesolr/content-­‐bias
  • 37. Control  Indexing  More  Precisely   hook_apachesolr_node_exclude($node, $namespace) in_array($node->type, variable_get( 'apachesolr_exclude_comments_types', array())) hook_node_update_index($node) • hook_node_update_index  output  added  to  body. • We  can  create  mulAple  documents  from  one  node   (e.g.  document  per  comment). hook_apachesolr_document_handlers($type, $namespace)
  • 38. Field  API  IntegraAon • Most  of  the  Field  API  integraAon  follows   directly  from  the  6.x-­‐2.x  CCK  integraAon. • In  Drupal  7,  we  match  field  types,  rather  than   looking  at  the  widget. • By  default,  the  data  will  be  indexed  to  Solr  as   mulA-­‐valued,  and  named  combining  the  field   module  and  name  sm_$module_$fieldname
  • 39. Typically  need  4  things: • What  field  types  (or  field  instances)  to  look   for  during  indexing. • The  data  type  to  use  in  the  index   (index_type) • A  funcAon  for  extracAng  the  data  from  the   field  while  indexing  (indexing_callback). • A  funcAon  for  displaying  the  data  from  the   field  during  searches  (display_callback).
  • 40. Field  API  IntegraAon hook_apachesolr_field_mappings_alter (&$mappings) $mappings['list_text'] = array( 'display_callback' => 'apachesolr_fields_list_display_callback', 'indexing_callback' => 'apachesolr_fields_list_indexing_callback', 'index_type' => 'string', );
  • 41.
  • 42.
  • 43. Analysis of an apachesolr search request search_view() $response = $query->search(...) $results = apachesolr_search_process_response ($response,$final_query) theme('search_results', $results, ...)
  • 44. Analysis of an apachesolr search request search_view() $response = $query->search(...) $results = apachesolr_search_process_response ($response,$final_query) theme('search_results', $results, ...)
  • 45. hook_menu: defines custom search paths /arts /arts/undergraduate /search/apachesolr_search/? filters=type%3Acatalog%20 ss_faculty%3AAR%20sm_level %3AUndergraduate
  • 46. hook_menu: defines custom search paths /arts /arts/undergraduate /arts/undergraduate/courses
  • 47. hook_menu: defines custom search paths // Implements hook_menu(). function mcgill_menu() { $items['arts/undergraduate/courses'] = array( 'page callback' => 'mcgill_courses_search', 'access arguments' => array('search content'), 'type' => MENU_CALLBACK, ); return $items; }
  • 48. Analysis of an apachesolr search request search_view() $response = $query->search(...) $results = apachesolr_search_process_response ($response,$final_query) theme('search_results', $results, ...)
  • 53. hook_menu_alter: changes the page callback // Implements hook_menu_alter(). function mcgill_menu_alter(&$items) { if (isset($items['search/apachesolr_search/%menu_tail'])) { $items['search']['page callback'] = 'mcgill_page'; $items['search/apachesolr_search/%menu_tail']['page callback'] = 'mcgill_page'; } }
  • 54. Analysis of an apachesolr search request search_view() $response = $query->search(...) $results = apachesolr_search_process_response ($response,$final_query) theme('search_results', $results, ...)
  • 55. An example Solr request
  • 56. Analysis of an apachesolr search request search_view() $response = $query->search(...) $results = apachesolr_search_process_response ($response,$final_query) theme('search_results', $results, ...)
  • 58. Analysis of an apachesolr search request search_view() $response = $query->search(...) $results = apachesolr_process_response($response, ...) $results = apachesolr_search_process_response ($response,$final_query) theme('search_results', $results, ...)
  • 59. hook_apachesolr_prepare/modify_query($query) // Run hook_apachesolr_prepare_query($query). // Cache the built query. $current_query = apachesolr_current_query($query); // Run hook_apachesolr_modify_query($query).
  • 62. hook_apachesolr_prepare_query($query): set a default Solr sort parameter
  • 63. hook_apachesolr_prepare_query($query): set a default Solr sort parameter $query->set_available_sort('sort_ss_course_code', array( 'title' => t('Course code'), 'default' => 'asc', )); $query->remove_available_sort('created'); $query->remove_available_sort('sort_name'); $query->remove_available_sort('type');
  • 64. hook_apachesolr_prepare_query($query): set a default Solr sort parameter if (!isset($_GET['solrsort'])) { if ($query->get_keys()) { $query->set_solrsort('score', 'asc'); } else { $query->set_solrsort('sort_ss_course_code', 'asc'); } }
  • 66. Should I use hook_apachesolr_prepare_query or hook_apachesolr_modify_query? /arts/undergraduate/courses
  • 67. Should I use hook_apachesolr_prepare_query or hook_apachesolr_modify_query?
  • 68. Should I use hook_apachesolr_prepare_query or hook_apachesolr_modify_query?
  • 69. Should I use hook_apachesolr_prepare_query or hook_apachesolr_modify_query?
  • 70. Should I use hook_apachesolr_prepare_query or hook_apachesolr_modify_query?
  • 71. Should I use hook_apachesolr_prepare_query or hook_apachesolr_modify_query?
  • 72. hook_apachesolr_modify_query($query): set default Solr fq parameters // Add filters for FACULTY/LEVEL/courses paths. if ($facet = get_faculty_from_path()) { $query->add_filter('ss_faculty', $facet); } if ($facet = get_level_from_path()) { $query->add_filter('sm_level', $facet); }
  • 74. hook_apachesolr_prepare/modify_query($query) Set Solr parameters in $query->params $query->params['fl'] .= ',ss_course_code'; $query->params['facet.limit'] = -1;
  • 75. Analysis of an apachesolr search request search_view() $response = $query->search(...) $results = apachesolr_search_process_response ($response,$final_query) theme('search_results', $results, ...)
  • 76. Analysis of an apachesolr search request search_view() $response = $query->search(...) $results = apachesolr_search_process_response ($response,$final_query) theme('search_results', $results, ...)
  • 78. theme_apachesolr_search_snippets: sets the snippet // Default implementation in apachesolr_search.module. function theme_apachesolr_search_snippets($document, $snippets) { return implode(' ... ', $snippets) . ' ...'; }
  • 80. theme_apachesolr_search_snippets: sets the snippet // Custom implementation in template.php. function mcgill_apachesolr_search_snippets($document, $snippets) { return 'anything you want!'; }
  • 81. Analysis of an apachesolr search request search_view() $response = $query->search(...) $results = apachesolr_search_process_response ($response,$final_query) theme('search_results', $results, ...)
  • 82. search-result.tpl.php: renders a single search result <?php print $result['node']->ss_course_code; ?> If this is user input use check_plain() - Solr can send you back the same (unsafe) user input you index. See apachesolr_clean_text() if you want to index text without tags.
  • 83. Extra thanks to James McKinney For use of his slides and for ideas. jpmckinney on drupal.org http://evolvingweb.ca/