Skip to content
M. Drew LaMar edited this page May 11, 2022 · 1 revision

Solr

To play with queries for the vagrant instance of Solr, use this URL: http://192.168.33.10:8445/solr/#/hubzero-solr-core/query

Development and testing instance

Using this Docker instance and following these instructions, run the following command:

docker run -d -v "$PWD/solrdata:/var/solr" -p 8983:8983 --name my_solr solr:6.6 solr-precreate collection1

Then go to http://localhost:8983/.

Note that we changed the name of the collection from gettingstarted in the example to collection1 so we could follow the following tutorial on multi-select faceting.

Key of Terms

Terms Meaning
q string query
fl field list, comma separated
fq filter query (can have more than one)
rows number of items returned (for pagination; -1 means all)

Important subtopics to learn

HubZero Solr importing and data information

The tags type:publication-tag are nested children of hubtype:publication. See app/components/com_publications/models/orm/version.php:searchResult() to see publication metadata that is stored in Solr.

Pivot facets

Query for tagged publications

  • hubtype:publication +{!parent which=hubtype:*}id:tag-91
  • Nested documents: https://solr.apache.org/guide/8_0/searching-nested-documents.html
  • app/components/com_publications/models/orm/version.php:searchResult contains code that indexes a publication for Solr
  • Get all tags of a publication
    • q=hubtype:publication
    • fl=id,[child parentFilter=hubtype:publication]
  • Since tags are child documents of publications, they are duplicated as many times as they are used

Might work in higher version of Solr (>= 7.4):

{
  "query": "hubtype:publication",
  "fields": "id",
  "facet": {
    "tags": {
      "type": "terms",
      "field": "description",
      "domain": {"blockChildren": "hubtype:publication",
                 "filter": "description:/(sgcoursesourcecourse[0-9]*)/"},
      "limit": 10
    }
  }
}

This will work on taxonomy related fields. JSON API

{
  "query": "hubtype:publication",
  "fields": "id, title",
  "limit": 20,
  "sort": "id desc",
  "facet": {
    "course": {
      "type": "terms",
      "field": "description",
      "domain": {"blockChildren": "hubtype:publication"},
      "prefix": "sgcoursesourcecourse",
      "limit": -1
    },
    "taxonomy": {
      "type": "terms",
      "field": "description",
      "domain": {"blockChildren": "hubtype:publication"},
      "prefix": "sgcoursesourcetaxonomy",
      "limit": -1
    }
  }
}

Multi-select faceting

https://solr.apache.org/guide/6_6/faceting.html#Faceting-TaggingandExcludingFilters

THIS MIGHT WORK

tag 5266 us Course 7 tag 5261 is Course 2 and tag 5553 is Taxonomy 2. It looks like the counts for Course only change when taxonomy is selected (which is what should happen)

{
  "query": "hubtype:publication",
  "filter": "{!parent tag=course which=hubtype:publication}(id:tag-5266 OR id:tag-5261) +{!parent tag=course which=hubtype:publication}(id:tag-5553)",
  "fields": "id, title",
  "limit": 20,
  "sort": "id desc",
  "facet": {
    "course": {
      "type": "terms",
      "field": "description",
      "excludeTags": "course",
      "domain": {"blockChildren": "hubtype:publication"},
      "prefix": "sgcoursesourcecourse",
      "limit": -1
    },
    "taxonomy: {
      "type": "terms",
      "field": "description",
      "excludeTags": "taxonomy",
      "domain": {"blockChildren": "hubtype:publication"},
      "prefix": "sgcoursesourcetaxonomy",
      "limit": -1
    }
  }
}

DOESN'T WORK

{
  "query": "category:clothes",
  "filter": "{!parent which=scope:product filter=}({!tag=color}color:black AND {!tag=size}size:L)",
  "facet": {
     "colors": {       
  	   "type": "terms",
       "field": "color",
       "excludeTags": "color",
       "domain": {"blockChildren": "category:clothes"},
       "limit": -1
     },  	 
     "sizes": {  
  	   "type": "terms",
       "field": "size",
       "excludeTags": "size",
       "domain": {"blockChildren": "category:clothes"},
       "limit": -1
     }
  }
}

DOES WORK (for 1)

{
  "query": "{!parent tag=top which=scope:product v=scope:sku}({!tag=color}color:black)",
  "filter": "{!tag=top}category:clothes",
  "facet": {
     "colors": {       
       "domain": {
         "excludeTags": "top",
         "filter": [
           "{!ex=color}scope:sku",
           "{!child of=scope:product v=scope:product}(category:clothes)"
        ]
       },
  	   "type": "terms",
       "field": "color",
       "limit": -1
     },  	 
     "sizes": {  
       "domain": {
         "excludeTags": "top",
         "filter": [
           "({!tag=color}color:black)",
           "{!child of=scope:product v=scope:product}(category:clothes)"
         ]
       },
  	   "type": "terms",
       "field": "size",
       "limit": -1
     }
  }
}

DOES WORK (FOR 2)

{
  "query": "{!parent tag=top which=scope:product v=scope:sku}({!tag=color}color:black AND {!tag=size}size:L)",
  "filter": "{!tag=top}category:clothes",
  "facet": {
     "colors": {       
       "domain": {
         "excludeTags": "top",
         "filter": [
           "{!tag=size}size:L",
           "{!child of=scope:product v=scope:product}(category:clothes)"
        ]
       },
  	   "type": "terms",
       "field": "color",
       "limit": -1
     },  	 
     "sizes": {  
       "domain": {
         "excludeTags": "top",
         "filter": [
           "{!tag=color}color:black",
           "{!child of=scope:product v=scope:product}(category:clothes)"
         ]
       },
  	   "type": "terms",
       "field": "size",
       "limit": -1
     }
  }
}

WORKS (FOR 3) (Note: Don't need local parameters !tag's in this case, cuz not excluding them)

{
  "query": "{!parent tag=top which=scope:product v=scope:sku}({!tag=color}color:black AND {!tag=size}(size:M OR size:L))",
  "filter": "{!tag=top}category:clothes",
  "facet": {
     "colors": {       
       "domain": {
         "excludeTags": "top",
         "filter": [
           "{!tag=size}(size:M OR size:L)",
           "{!child of=scope:product v=scope:product}(category:clothes)"
        ]
       },
  	   "type": "terms",
       "field": "color",
       "limit": -1
     },  	 
     "sizes": {  
       "domain": {
         "excludeTags": "top",
         "filter": [
           "{!tag=color}color:black",
           "{!child of=scope:product v=scope:product}(category:clothes)"
         ]
       },
  	   "type": "terms",
       "field": "size",
       "limit": -1
     }
  }
}

Solarium

Examples

Multi-select faceting

Example files located in ~/dev/solarium.

<?php

# ~/dev/solarium/facet-nested-multi-select.php

require_once(__DIR__.'/init.php');
htmlHeader();

// create a client instance
$client = new Solarium\Client($adapter, $eventDispatcher, $config);

// get a select query instance
$query = $client->createSelect();

// set the query
$query->setQuery('{!parent tag=top which=scope:product v=scope:sku}(color:black AND (size:M OR size:L))');

// get the facetset component
$facetSet = $query->getFacetSet();

// create a facet field instance and set options
$colorTerms = new Solarium\Component\Facet\JsonTerms(['local_key' => 'colors',
  'field' => 'color',
  'domain' => ['excludeTags' => 'top',
               'filter' => ["size:M OR size:L",
                            "{!child of=scope:product v=scope:product}(category:clothes)"]
              ],
  'limit' => -1,
  'numBuckets' => true]);

// create a facet field instance and set options
$sizeTerms = new Solarium\Component\Facet\JsonTerms(['local_key' => 'sizes',
  'field' => 'size',
  'domain' => ['excludeTags' => 'top',
               'filter' => ["color:black",
                            "{!child of=scope:product v=scope:product}(category:clothes)"]
              ],
  'limit' => -1,
  'numBuckets' => true]);

// add json terms instance to the facetSet
$facetSet->addFacet($colorTerms);
$facetSet->addFacet($sizeTerms);

// this executes the query and returns the result
$resultset = $client->select($query);

// display the total number of documents found by Solr
echo 'NumFound: '.$resultset->getNumFound();

// display facet counts
echo '<hr/>Facet counts for field "color":<br/>';
$facet = $resultset->getFacetSet()->getFacet('colors');
echo 'NumBuckets: '.$facet->getNumBuckets().' (total possible number of buckets, only available when \'numBuckets\'=>true in JsonTerms)<br/>';
echo 'count(): '.$facet->count().' (number of buckets returned)<br/>';

//  Note: use instanceof Solarium\Component\Result\Facet\Buckets to differentiate from standard field facets.
foreach ($facet as $bucket) {
    echo $bucket->getValue() . ' [' . $bucket->getCount() . ']<br/>';
}

// display facet counts
echo '<hr/>Facet counts for field "size":<br/>';
$facet = $resultset->getFacetSet()->getFacet('sizes');
echo 'NumBuckets: '.$facet->getNumBuckets().' (total possible number of buckets, only available when \'numBuckets\'=>true in JsonTerms)<br/>';
echo 'count(): '.$facet->count().' (number of buckets returned)<br/>';

//  Note: use instanceof Solarium\Component\Result\Facet\Buckets to differentiate from standard field facets.
foreach ($facet as $bucket) {
    echo $bucket->getValue() . ' [' . $bucket->getCount() . ']<br/>';
}

// show documents using the resultset iterator
foreach ($resultset as $document) {

    echo '<hr/><table>';
    echo '<tr><th>id</th><td>' . $document->id . '</td></tr>';
    echo '<tr><th>name</th><td>' . $document->name . '</td></tr>';
    echo '<tr><th>price</th><td>' . $document->price . '</td></tr>';
    echo '</table>';
}

htmlFooter();

Clone this wiki locally