title: "protected phrase" in Solr
body: <p>A customer of mine is a photo agency specialized in photojournalism (well, and gossip), so many of their customers' searches revolve around specific people.</p>
  
  <p>We index about 1.5m documents, with full-text search on headline and caption; and full-text search without stemming on tags. We have a decent list of stop words, and they provide a list of protected words that they feel are not stemmed correctly.
  We are using Dismax to search over headline, caption and tags, with different boosts)
  This is all working pretty nicely.</p>
  
  <p>However, a few people are proving tricky to get right. For instance, Al Gore. In Italian "al" is a stop word, so a simple query for `al gore' (without quotes) becomes:</p>
  
  <pre><code>+((DisjunctionMaxQuery((caption_text:gor | tags_text:gore^100.0 | headline_text:gor)))~1) ()
  </code></pre>
  
  <p>That does return hits for the ex VP, but of course also for "Lesley Gore" and "Tipper Gore"; and also, because of stemming, hits for "Gori" and more.
  Leaving aside sorting for a second, it does clutter up results, and I'd like to do better.</p>
  
  <p>Wrapping the search terms in quotes doesn't help, "al" gets stripped away anyway.
  Marking "gore" as a protected word gets me halfway there, limiting the number of false positives.
  I tried playing with SynonymFilterFactory too, but didn't get too far--I have the SynonymFilterFactory as the first filter, so "al" gets removed anyway.</p>
  
  <p>What I think I really need is a way of tokenizing "al gore" as a single token. Is there anything that will allow me to do that, for a set of configurable "phrases"?
  Is there another approach I'm overlooking? solr.CommonGramsFilterFactory perhaps?</p>
  
  <p>Some more background info: we are using Solr 1.4.0.
  Relevant portions of schema.xml</p>
  
  <pre><code>&lt;!-- used for headline and caption --&gt;
  &lt;fieldType name="text" class="solr.TextField" omitNorms="false"&gt;
    &lt;analyzer type="index"&gt;
      &lt;tokenizer class="solr.StandardTokenizerFactory"/&gt;
      &lt;filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.it.txt"/&gt;
      &lt;filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0"/&gt;
      &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
      &lt;filter class="solr.SnowballPorterFilterFactory" language="Italian" protected="protwords.txt"/&gt;
      &lt;filter class="solr.RemoveDuplicatesTokenFilterFactory"/&gt;
    &lt;/analyzer&gt;
    &lt;analyzer type="query"&gt;
      &lt;tokenizer class="solr.StandardTokenizerFactory"/&gt;
      &lt;filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/&gt;
      &lt;filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.it.txt"/&gt;
      &lt;filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0"/&gt;
      &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
      &lt;filter class="solr.SnowballPorterFilterFactory" language="Italian" protected="protwords.txt"/&gt;
      &lt;filter class="solr.RemoveDuplicatesTokenFilterFactory"/&gt;
    &lt;/analyzer&gt;
  &lt;/fieldType&gt;
  
  &lt;fieldType name="tagsText" class="solr.TextField" sortMissingLast="true" omitNorms="false"&gt;
    &lt;analyzer type="index"&gt;
      &lt;tokenizer class="solr.StandardTokenizerFactory"/&gt;
      &lt;filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.it.txt"/&gt;
      &lt;filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0"/&gt;   
      &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
      &lt;filter class="solr.RemoveDuplicatesTokenFilterFactory"/&gt;
    &lt;/analyzer&gt;
    &lt;analyzer type="query"&gt;
      &lt;tokenizer class="solr.StandardTokenizerFactory"/&gt;
      &lt;filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/&gt;
      &lt;filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.it.txt"/&gt;
      &lt;filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0"/&gt;
      &lt;filter class="solr.LowerCaseFilterFactory"/&gt;  
      &lt;filter class="solr.RemoveDuplicatesTokenFilterFactory"/&gt;
    &lt;/analyzer&gt;
  &lt;/fieldType&gt;
  </code></pre>