SlideShare a Scribd company logo
1 of 84
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 - patternsRafał Kuć
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 MinutesAzim Kurt
 
Getting Creative with WordPress Queries, Again
Getting Creative with WordPress Queries, AgainGetting Creative with WordPress Queries, Again
Getting Creative with WordPress Queries, AgainDrewAPicture
 
[제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 SecurityColin 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 2016Colin 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 2016Colin 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] 2016Colin 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ć, SematextLucidworks
 
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 tableMahabubur 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
 
UITableView Pain Points
UITableView Pain PointsUITableView Pain Points
UITableView Pain PointsKen 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 2012Rafael Dohms
 
Drupal 8: Forms
Drupal 8: FormsDrupal 8: Forms
Drupal 8: Formsdrubb
 
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
 
Mysql query optimization
Mysql query optimizationMysql query optimization
Mysql query optimizationBaohua 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_CLEAREDLuis Caballero Bonilla
 
Francy lorena mancholacruz_actividad1_2mapac
Francy lorena mancholacruz_actividad1_2mapacFrancy lorena mancholacruz_actividad1_2mapac
Francy lorena mancholacruz_actividad1_2mapaclorena cruz
 
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 cityAntara 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 ScenarioSven Jörges
 
Sprinklr vs Salesforce
Sprinklr vs SalesforceSprinklr vs Salesforce
Sprinklr vs SalesforceEmpire Selling
 
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 ErfahrungsberichtSven Jörges
 
Gestión y control de calidad
Gestión y control de calidadGestión y control de calidad
Gestión y control de calidadRaúl Cordova
 
Activiti: a developer-friendly process engine
Activiti: a developer-friendly process engineActiviti: a developer-friendly process engine
Activiti: a developer-friendly process engineTravis Carlson
 
Επαναληπτικό φύλλο εργασίας,, β γυμν Αρχαία, ενότ 1-5
Επαναληπτικό φύλλο εργασίας,, β γυμν Αρχαία, ενότ 1-5Επαναληπτικό φύλλο εργασίας,, β γυμν Αρχαία, ενότ 1-5
Επαναληπτικό φύλλο εργασίας,, β γυμν Αρχαία, ενότ 1-5chavalesnick
 
Φύλλο εργασίας αρχαια Α΄ γυμν 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 2014NoSQLmatters
 
Cassandra summit
Cassandra summitCassandra summit
Cassandra summitmattstump
 
dcs plus Catalogue 2015
dcs plus Catalogue 2015dcs plus Catalogue 2015
dcs plus Catalogue 2015dcs 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 Applicationselliando dias
 
Resource Routing in ExpressionEngine
Resource Routing in ExpressionEngineResource Routing in ExpressionEngine
Resource Routing in ExpressionEngineMichaelRog
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony TechniquesKris Wallsmith
 
The State of Lithium
The State of LithiumThe State of Lithium
The State of LithiumNate Abele
 
Solr integration in Magento Enterprise
Solr integration in Magento EnterpriseSolr integration in Magento Enterprise
Solr integration in Magento EnterpriseTobias 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 2011camp_drupal_ua
 
第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 DatasourceKaz Watanabe
 
Elasticsearch and Symfony Integration - Debarko De
Elasticsearch and Symfony Integration - Debarko DeElasticsearch and Symfony Integration - Debarko De
Elasticsearch and Symfony Integration - Debarko DeDebarko De
 
DrupalCamp Foz - Novas APIs Drupal 7
DrupalCamp Foz - Novas APIs Drupal 7DrupalCamp Foz - Novas APIs Drupal 7
DrupalCamp Foz - Novas APIs Drupal 7chuvainc
 
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 ThingChris 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.pdfAcquia
 
Acquia Webinar Deck - 9_13 .pdf
Acquia Webinar Deck - 9_13 .pdfAcquia Webinar Deck - 9_13 .pdf
Acquia Webinar Deck - 9_13 .pdfAcquia
 
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 LevelAcquia
 
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.pdfAcquia
 
May Partner Bootcamp 2022
May Partner Bootcamp 2022May Partner Bootcamp 2022
May Partner Bootcamp 2022Acquia
 
April Partner Bootcamp 2022
April Partner Bootcamp 2022April Partner Bootcamp 2022
April Partner Bootcamp 2022Acquia
 
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 CXAcquia
 
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 WorkflowAcquia
 
September Partner Bootcamp
September Partner BootcampSeptember Partner Bootcamp
September Partner BootcampAcquia
 
August partner bootcamp
August partner bootcampAugust partner bootcamp
August partner bootcampAcquia
 
July 2021 Partner Bootcamp
July  2021 Partner BootcampJuly  2021 Partner Bootcamp
July 2021 Partner BootcampAcquia
 
May Partner Bootcamp
May Partner BootcampMay Partner Bootcamp
May Partner BootcampAcquia
 
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 EASYAcquia
 
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 MachineAcquia
 
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 LeadsAcquia
 
April partner bootcamp deck cookieless future
April partner bootcamp deck  cookieless futureApril partner bootcamp deck  cookieless future
April partner bootcamp deck cookieless futureAcquia
 
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 solutionsAcquia
 
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 2021Acquia
 

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

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 

Recently uploaded (20)

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 

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/