You are viewing a plain text version of this content. The canonical link for it is here.
Posted to solr-user@lucene.apache.org by Kent Iversen <ke...@webstep.no> on 2017/02/01 07:42:22 UTC

DIH - Parent-Child-Problems - GrapQuery-Or-BlockJoin - Order with Orderlines

I'm a newbie to Solr and can't seem to get this to work, properly. Gonna
use Order with Orderlines as an example.
And I'm using Solr 6.3.0


ORDER
----------------------------------------
| orderid  |  customername     |
----------------------------------------
|      1      |     ACME                |
----------------------------------------
|      2      |     LOREM IPSUM |
----------------------------------------

ORDERLINE
----------------------------------------------------------------
| orderlineid | orderid  |  productname | quantity |
----------------------------------------------------------------
|      1           |     1       |       KNIFE      |      10     |
----------------------------------------------------------------
|      2           |     1       |       FORK      |       15     |
----------------------------------------------------------------
|      3           |     1       |       SPOON   |       12     |
----------------------------------------------------------------
|      4           |     2       |       FORK      |       25     |
----------------------------------------------------------------

Now, I would like to return the customer name and the products and quantity
when querying for either the customer name or a product name.

1)
QUERY for customer name = "ACME"
Wanted result (pseudo style):

Parent: ACME

Child:
{productname:KNIFE},
{quantity:10}

Child:
{productname:FORK},
{quantity:15}

Child:
{productname:SPOON},
{quantity:12}

2)
QUERY for product name = "FORK"
Wanted result (pseudo style):

Parent: ACME

Child:
{productname : FORK},
{quantity : 15}


Parent: LOREM IPSUM

Child:
{productname : FORK},
{quantity : 25}


Actual response when querying for orderid:1 (in the queryeditor in Solr)

(http://localhost:8983/solr/order/select?indent=on&q=orderid:1&wt=json)

{
  "responseHeader":{
    "status":0,
    "QTime":0,
    "params":{
      "q":"orderid:1",
      "indent":"on",
      "wt":"json",
      "_":"1485913597768"}},
  "response":{"numFound":3,"start":0,"docs":[
      {
        "orderlineid":1,
        "orderid":1,
        "quantity":10,
        "productname":"KNIFE"},
      {
        "orderlineid":2,
        "orderid":1,
        "quantity":15,
        "productname":"FORK"},
      {
        "orderlineid":3,
        "orderid":1,
        "quantity":12,
        "quantity":"SPOON"},
      {
        "orderid":1,
        "customername":"ACME",
        "_version_":1558094660321148928}]
  }}

Don't see the _child_ marker here, so it doesn't seems like what I have
seen other people get in the response.

1) What is wrong with my configuration? How should it be?
There is a relationship between order and orderline, and that is the order
id, which is defined as a uniqueKey in managed-schema.xml
2) How can I get the customer name, product name and quantity when
searching either for customer name, or product name? For instance, which
customer bought FORKS?
3) How to use or append either GrapQuery or BlockJoin to give me back the
result I want?

Please advice

Regards
Kent



solrconfig.xml
----------------------

<!-- Necessary libs -->
<lib
dir="${solr.install.dir:../../../..}/contrib/dataimporthandler-extras/lib"
regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/"
regex="solr-dataimporthandler-\d.*\.jar" />
...

<!-- The requesthandler -->
<requestHandler name="/dataimport"
class="org.apache.solr.handler.dataimport.DataImportHandler">
    <lst name="defaults">
      <str name="config">data-config.xml</str>
    </lst>
</requestHandler>



data-config.xml
--------------------------
<dataConfig>

   <!-- Removed the datasource config -->
   <dataSource driver="" url="" user="" password=""/>

    <document name="orders">
        <entity name="order" rootEntity='true' query="select orderid,
customername from ORDER">

            <field column="ORDERID" name="orderid" />
            <field column="CUSTOMERNAME" name="customername" />

            <entity name="orderline" child="true"
                query="select ol.orderlineid, ol.orderid, ol.productname,
ol.quantity from ORDERLINE ol where ol.orderid =  ${order.orderid}">

                <field column="ORDERID" name="orderid" />
                <field column="ORDERLINEID" name="orderlineid" />
                <field column="PRODUCTNAME" name="productname" />
                <field column="QUANTITY" name="quantity" />
            </entity>
    </entity>
    </document>
</dataConfig>


managed-data.xml
--------------------------

<?xml version="1.0" encoding="UTF-8" ?>

<schema name="order-and-orderlines-example" version="1.6">

    <field name="_version_"     type="long"         indexed="false"
stored="false"/>
    <field name="_root_"        type="string"       indexed="true"
 stored="false" docValues="false" />
    <field name="_text_"        type="text_general" indexed="true"
 stored="false" multiValued="true"/>

<!-- fields for order and orderlines -->
    <field name="orderid"       type="long"   indexed="true"  stored="true"
 multiValued="false" />
    <field name="orderlineid"   type="long"   indexed="true"  stored="true"
 multiValued="false" />
    <field name="customername"  type="string" indexed="true"  stored="true"
 multiValued="false" />
    <field name="productname"   type="string" indexed="true"  stored="true"
 multiValued="false" />
    <field name="quantity"      type="long"   indexed="false" stored="true"
multiValued="false" />



    <!-- Only enabled in the "schemaless" data-driven example (assuming the
client
         does not know what fields may be searched) because it's very
expensive to index everything twice. -->
    <copyField source="*" dest="_text_"/>

    <uniqueKey>orderid</uniqueKey>

        <fieldType name="string" class="solr.StrField"
sortMissingLast="true" docValues="true" />
    <fieldType name="strings" class="solr.StrField" sortMissingLast="true"
multiValued="true" docValues="true" />

    <!-- boolean type: "true" or "false" -->
    <fieldType name="boolean" class="solr.BoolField"
sortMissingLast="true"/>

    <fieldType name="booleans" class="solr.BoolField"
sortMissingLast="true" multiValued="true"/>

    <!-- sortMissingLast and sortMissingFirst attributes are optional
attributes are
         currently supported on types that are sorted internally as strings
         and on numeric types.
       This includes "string","boolean", and, as of 3.5 (and 4.x),
       int, float, long, date, double, including the "Trie" variants.
       - If sortMissingLast="true", then a sort on this field will cause
documents
         without the field to come after documents with the field,
         regardless of the requested sort order (asc or desc).
       - If sortMissingFirst="true", then a sort on this field will cause
documents
         without the field to come before documents with the field,
         regardless of the requested sort order.
       - If sortMissingLast="false" and sortMissingFirst="false" (the
default),
         then default lucene sorting will be used which places docs without
the
         field first in an ascending sort and last in a descending sort.
    -->

    <!--
      Default numeric field types. For faster range queries, consider the
tint/tfloat/tlong/tdouble types.

      These fields support doc values, but they require the field to be
      single-valued and either be required or have a default value.
    -->
    <fieldType name="int" class="solr.TrieIntField" docValues="true"
precisionStep="0" positionIncrementGap="0"/>
    <fieldType name="float" class="solr.TrieFloatField" docValues="true"
precisionStep="0" positionIncrementGap="0"/>
    <fieldType name="long" class="solr.TrieLongField" docValues="true"
precisionStep="0" positionIncrementGap="0"/>
    <fieldType name="double" class="solr.TrieDoubleField" docValues="true"
precisionStep="0" positionIncrementGap="0"/>

    <fieldType name="ints" class="solr.TrieIntField" docValues="true"
precisionStep="0" positionIncrementGap="0" multiValued="true"/>
    <fieldType name="floats" class="solr.TrieFloatField" docValues="true"
precisionStep="0" positionIncrementGap="0" multiValued="true"/>
    <fieldType name="longs" class="solr.TrieLongField" docValues="true"
precisionStep="0" positionIncrementGap="0" multiValued="true"/>
    <fieldType name="doubles" class="solr.TrieDoubleField" docValues="true"
precisionStep="0" positionIncrementGap="0" multiValued="true"/>

    <!--
     Numeric field types that index each value at various levels of
precision
     to accelerate range queries when the number of values between the range
     endpoints is large. See the javadoc for NumericRangeQuery for internal
     implementation details.

     Smaller precisionStep values (specified in bits) will lead to more
tokens
     indexed per value, slightly larger index size, and faster range
queries.
     A precisionStep of 0 disables indexing at different precision levels.
    -->
    <fieldType name="tint" class="solr.TrieIntField" docValues="true"
precisionStep="8" positionIncrementGap="0"/>
    <fieldType name="tfloat" class="solr.TrieFloatField" docValues="true"
precisionStep="8" positionIncrementGap="0"/>
    <fieldType name="tlong" class="solr.TrieLongField" docValues="true"
precisionStep="8" positionIncrementGap="0"/>
    <fieldType name="tdouble" class="solr.TrieDoubleField" docValues="true"
precisionStep="8" positionIncrementGap="0"/>

    <fieldType name="tints" class="solr.TrieIntField" docValues="true"
precisionStep="8" positionIncrementGap="0" multiValued="true"/>
    <fieldType name="tfloats" class="solr.TrieFloatField" docValues="true"
precisionStep="8" positionIncrementGap="0" multiValued="true"/>
    <fieldType name="tlongs" class="solr.TrieLongField" docValues="true"
precisionStep="8" positionIncrementGap="0" multiValued="true"/>
    <fieldType name="tdoubles" class="solr.TrieDoubleField"
docValues="true" precisionStep="8" positionIncrementGap="0"
multiValued="true"/>

    <!-- The format for this date field is of the form
1995-12-31T23:59:59Z, and
         is a more restricted form of the canonical representation of
dateTime
         http://www.w3.org/TR/xmlschema-2/#dateTime
         The trailing "Z" designates UTC time and is mandatory.
         Optional fractional seconds are allowed: 1995-12-31T23:59:59.999Z
         All other components are mandatory.

         Expressions can also be used to denote calculations that should be
         performed relative to "NOW" to determine the value, ie...

               NOW/HOUR
                  ... Round to the start of the current hour
               NOW-1DAY
                  ... Exactly 1 day prior to now
               NOW/DAY+6MONTHS+3DAYS
                  ... 6 months and 3 days in the future from the start of
                      the current day

         Consult the TrieDateField javadocs for more information.

         Note: For faster range queries, consider the tdate type
      -->
    <fieldType name="date" class="solr.TrieDateField" docValues="true"
precisionStep="0" positionIncrementGap="0"/>
    <fieldType name="dates" class="solr.TrieDateField" docValues="true"
precisionStep="0" positionIncrementGap="0" multiValued="true"/>

    <!-- A Trie based date field for faster date range queries and date
faceting. -->
    <fieldType name="tdate" class="solr.TrieDateField" docValues="true"
precisionStep="6" positionIncrementGap="0"/>

    <fieldType name="tdates" class="solr.TrieDateField" docValues="true"
precisionStep="6" positionIncrementGap="0" multiValued="true"/>


    <!--Binary data type. The data should be sent/retrieved in as Base64
encoded Strings -->
    <fieldType name="binary" class="solr.BinaryField"/>

    <!-- The "RandomSortField" is not used to store or search any
         data.  You can declare fields of this type it in your schema
         to generate pseudo-random orderings of your docs for sorting
         or function purposes.  The ordering is generated based on the field
         name and the version of the index. As long as the index version
         remains unchanged, and the same field name is reused,
         the ordering of the docs will be consistent.
         If you want different psuedo-random orderings of documents,
         for the same version of the index, use a dynamicField and
         change the field name in the request.
     -->
    <fieldType name="random" class="solr.RandomSortField" indexed="true" />

    <!-- solr.TextField allows the specification of custom text analyzers
         specified as a tokenizer and a list of token filters. Different
         analyzers may be specified for indexing and querying.

         The optional positionIncrementGap puts space between multiple
fields of
         this type on the same document, with the purpose of preventing
false phrase
         matching across fields.

         For more info on customizing your analyzer chain, please see
         http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters
     -->

    <!-- One can also specify an existing Analyzer class that has a
         default constructor via the class attribute on the analyzer
element.
         Example:
    <fieldType name="text_greek" class="solr.TextField">
      <analyzer class="org.apache.lucene.analysis.el.GreekAnalyzer"/>
    </fieldType>
    -->

    <!-- A text field that only splits on whitespace for exact matching of
words -->
    <dynamicField name="*_ws" type="text_ws"  indexed="true"
 stored="true"/>
    <fieldType name="text_ws" class="solr.TextField"
positionIncrementGap="100">
      <analyzer>
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
      </analyzer>
    </fieldType>

    <!-- A general text field that has reasonable, generic
         cross-language defaults: it tokenizes with StandardTokenizer,
         removes stop words from case-insensitive "stopwords.txt"
         (empty by default), and down cases.  At query time only, it
         also applies synonyms.
    -->
    <fieldType name="text_general" class="solr.TextField"
positionIncrementGap="100" multiValued="true">
      <analyzer type="index">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true"
words="stopwords.txt" />
        <!-- in this example, we will only use synonyms at query time
        <filter class="solr.SynonymFilterFactory"
synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
        -->
        <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true"
words="stopwords.txt" />
        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"
ignoreCase="true" expand="true"/>
        <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
    </fieldType>

    <!-- A text field with defaults appropriate for English: it
         tokenizes with StandardTokenizer, removes English stop words
         (lang/stopwords_en.txt), down cases, protects words from
protwords.txt, and
         finally applies Porter's stemming.  The query time analyzer
         also applies synonyms from synonyms.txt. -->
    <dynamicField name="*_txt_en" type="text_en"  indexed="true"
 stored="true"/>
    <fieldType name="text_en" class="solr.TextField"
positionIncrementGap="100">
      <analyzer type="index">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <!-- in this example, we will only use synonyms at query time
        <filter class="solr.SynonymFilterFactory"
synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
        -->
        <!-- Case insensitive stop word removal.
        -->
        <filter class="solr.StopFilterFactory"
                ignoreCase="true"
                words="lang/stopwords_en.txt"
            />
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.EnglishPossessiveFilterFactory"/>
        <filter class="solr.KeywordMarkerFilterFactory"
protected="protwords.txt"/>
        <!-- Optionally you may want to use this less aggressive stemmer
instead of PorterStemFilterFactory:
        <filter class="solr.EnglishMinimalStemFilterFactory"/>
        -->
        <filter class="solr.PorterStemFilterFactory"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"
ignoreCase="true" expand="true"/>
        <filter class="solr.StopFilterFactory"
                ignoreCase="true"
                words="lang/stopwords_en.txt"
        />
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.EnglishPossessiveFilterFactory"/>
        <filter class="solr.KeywordMarkerFilterFactory"
protected="protwords.txt"/>
        <!-- Optionally you may want to use this less aggressive stemmer
instead of PorterStemFilterFactory:
        <filter class="solr.EnglishMinimalStemFilterFactory"/>
        -->
        <filter class="solr.PorterStemFilterFactory"/>
      </analyzer>
    </fieldType>

    <!-- A text field with defaults appropriate for English, plus
         aggressive word-splitting and autophrase features enabled.
         This field is just like text_en, except it adds
         WordDelimiterFilter to enable splitting and matching of
         words on case-change, alpha numeric boundaries, and
         non-alphanumeric chars.  This means certain compound word
         cases will work, for example query "wi fi" will match
         document "WiFi" or "wi-fi".
    -->
    <dynamicField name="*_txt_en_split" type="text_en_splitting"
 indexed="true"  stored="true"/>
    <fieldType name="text_en_splitting" class="solr.TextField"
positionIncrementGap="100" autoGeneratePhraseQueries="true">
      <analyzer type="index">
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <!-- in this example, we will only use synonyms at query time
        <filter class="solr.SynonymFilterFactory"
synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
        -->
        <!-- Case insensitive stop word removal.
        -->
        <filter class="solr.StopFilterFactory"
                ignoreCase="true"
                words="lang/stopwords_en.txt"
        />
        <filter class="solr.WordDelimiterFilterFactory"
generateWordParts="1" generateNumberParts="1" catenateWords="1"
catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.KeywordMarkerFilterFactory"
protected="protwords.txt"/>
        <filter class="solr.PorterStemFilterFactory"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"
ignoreCase="true" expand="true"/>
        <filter class="solr.StopFilterFactory"
                ignoreCase="true"
                words="lang/stopwords_en.txt"
        />
        <filter class="solr.WordDelimiterFilterFactory"
generateWordParts="1" generateNumberParts="1" catenateWords="0"
catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.KeywordMarkerFilterFactory"
protected="protwords.txt"/>
        <filter class="solr.PorterStemFilterFactory"/>
      </analyzer>
    </fieldType>

    <!-- Less flexible matching, but less false matches.  Probably not
ideal for product names,
         but may be good for SKUs.  Can insert dashes in the wrong place
and still match. -->
    <dynamicField name="*_txt_en_split_tight"
type="text_en_splitting_tight"  indexed="true"  stored="true"/>
    <fieldType name="text_en_splitting_tight" class="solr.TextField"
positionIncrementGap="100" autoGeneratePhraseQueries="true">
      <analyzer>
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"
ignoreCase="true" expand="false"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true"
words="lang/stopwords_en.txt"/>
        <filter class="solr.WordDelimiterFilterFactory"
generateWordParts="0" generateNumberParts="0" catenateWords="1"
catenateNumbers="1" catenateAll="0"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.KeywordMarkerFilterFactory"
protected="protwords.txt"/>
        <filter class="solr.EnglishMinimalStemFilterFactory"/>
        <!-- this filter can remove any duplicate tokens that appear at the
same position - sometimes
             possible with WordDelimiterFilter in conjuncton with stemming.
-->
        <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
      </analyzer>
    </fieldType>

    <!-- Just like text_general except it reverses the characters of
         each token, to enable more efficient leading wildcard queries.
    -->
    <dynamicField name="*_txt_rev" type="text_general_rev"  indexed="true"
 stored="true"/>
    <fieldType name="text_general_rev" class="solr.TextField"
positionIncrementGap="100">
      <analyzer type="index">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true"
words="stopwords.txt" />
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.ReversedWildcardFilterFactory"
withOriginal="true"
                maxPosAsterisk="3" maxPosQuestion="2"
maxFractionAsterisk="0.33"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"
ignoreCase="true" expand="true"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true"
words="stopwords.txt" />
        <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
    </fieldType>

    <dynamicField name="*_phon_en" type="phonetic_en"  indexed="true"
 stored="true"/>
    <fieldType name="phonetic_en" stored="false" indexed="true"
class="solr.TextField" >
      <analyzer>
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.DoubleMetaphoneFilterFactory" inject="false"/>
      </analyzer>
    </fieldType>

    <!-- lowercases the entire field value, keeping it as a single token.
 -->
    <dynamicField name="*_s_lower" type="lowercase"  indexed="true"
 stored="true"/>
    <fieldType name="lowercase" class="solr.TextField"
positionIncrementGap="100">
      <analyzer>
        <tokenizer class="solr.KeywordTokenizerFactory"/>
        <filter class="solr.LowerCaseFilterFactory" />
      </analyzer>
    </fieldType>

    <!--
      Example of using PathHierarchyTokenizerFactory at index time, so
      queries for paths match documents at that path, or in descendent paths
    -->
    <dynamicField name="*_descendent_path" type="descendent_path"
 indexed="true"  stored="true"/>
    <fieldType name="descendent_path" class="solr.TextField">
      <analyzer type="index">
        <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/"
/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.KeywordTokenizerFactory" />
      </analyzer>
    </fieldType>

    <!--
      Example of using PathHierarchyTokenizerFactory at query time, so
      queries for paths match documents at that path, or in ancestor paths
    -->
    <dynamicField name="*_ancestor_path" type="ancestor_path"
 indexed="true"  stored="true"/>
    <fieldType name="ancestor_path" class="solr.TextField">
      <analyzer type="index">
        <tokenizer class="solr.KeywordTokenizerFactory" />
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/"
/>
      </analyzer>
    </fieldType>

    <!-- since fields of this type are by default not stored or indexed,
         any data added to them will be ignored outright.  -->
    <fieldType name="ignored" stored="false" indexed="false"
docValues="false" multiValued="true" class="solr.StrField" />

    <!-- This point type indexes the coordinates as separate fields
(subFields)
      If subFieldType is defined, it references a type, and a dynamic field
      definition is created matching *___<typename>.  Alternately, if
      subFieldSuffix is defined, that is used to create the subFields.
      Example: if subFieldType="double", then the coordinates would be
        indexed in fields myloc_0___double,myloc_1___double.
      Example: if subFieldSuffix="_d" then the coordinates would be indexed
        in fields myloc_0_d,myloc_1_d
      The subFields are an implementation detail of the fieldType, and end
      users normally should not need to know about them.
     -->
    <dynamicField name="*_point" type="point"  indexed="true"
 stored="true"/>
    <fieldType name="point" class="solr.PointType" dimension="2"
subFieldSuffix="_d"/>

    <!-- A specialized field for geospatial search. If indexed, this
fieldType must not be multivalued. -->
    <fieldType name="location" class="solr.LatLonType"
subFieldSuffix="_coordinate"/>

    <!-- An alternative geospatial field type new to Solr 4.  It supports
multiValued and polygon shapes.
      For more information about this and other Spatial fields new to Solr
4, see:
      http://wiki.apache.org/solr/SolrAdaptersForLuceneSpatial4
    -->
    <fieldType name="location_rpt"
class="solr.SpatialRecursivePrefixTreeFieldType"
               geo="true" distErrPct="0.025" maxDistErr="0.001"
distanceUnits="kilometers" />

    <!-- Money/currency field type. See
http://wiki.apache.org/solr/MoneyFieldType
        Parameters:
          defaultCurrency: Specifies the default currency if none
specified. Defaults to "USD"
          precisionStep:   Specifies the precisionStep for the TrieLong
field used for the amount
          providerClass:   Lets you plug in other exchange provider backend:
                           solr.FileExchangeRateProvider is the default and
takes one parameter:
                             currencyConfig: name of an xml file holding
exchange rates
                           solr.OpenExchangeRatesOrgProvider uses rates
from openexchangerates.org:
                             ratesFileLocation: URL or path to rates JSON
file (default latest.json on the web)
                             refreshInterval: Number of minutes between
each rates fetch (default: 1440, min: 60)
    -->
    <fieldType name="currency" class="solr.CurrencyField" precisionStep="8"
defaultCurrency="USD" currencyConfig="currency.xml" />

</schema>

Re: DIH - Parent-Child-Problems - GrapQuery-Or-BlockJoin - Order with Orderlines

Posted by Mikhail Khludnev <gg...@gmail.com>.
Have you checked
https://cwiki.apache.org/confluence/display/solr/Other+Parsers#OtherParsers-BlockJoinQueryParsers
?

01 февр. 2017 г. 10:42 пользователь "Kent Iversen" <ke...@webstep.no>
написал:

> I'm a newbie to Solr and can't seem to get this to work, properly. Gonna
> use Order with Orderlines as an example.
> And I'm using Solr 6.3.0
>
>
> ORDER
> ----------------------------------------
> | orderid  |  customername     |
> ----------------------------------------
> |      1      |     ACME                |
> ----------------------------------------
> |      2      |     LOREM IPSUM |
> ----------------------------------------
>
> ORDERLINE
> ----------------------------------------------------------------
> | orderlineid | orderid  |  productname | quantity |
> ----------------------------------------------------------------
> |      1           |     1       |       KNIFE      |      10     |
> ----------------------------------------------------------------
> |      2           |     1       |       FORK      |       15     |
> ----------------------------------------------------------------
> |      3           |     1       |       SPOON   |       12     |
> ----------------------------------------------------------------
> |      4           |     2       |       FORK      |       25     |
> ----------------------------------------------------------------
>
> Now, I would like to return the customer name and the products and quantity
> when querying for either the customer name or a product name.
>
> 1)
> QUERY for customer name = "ACME"
> Wanted result (pseudo style):
>
> Parent: ACME
>
> Child:
> {productname:KNIFE},
> {quantity:10}
>
> Child:
> {productname:FORK},
> {quantity:15}
>
> Child:
> {productname:SPOON},
> {quantity:12}
>
> 2)
> QUERY for product name = "FORK"
> Wanted result (pseudo style):
>
> Parent: ACME
>
> Child:
> {productname : FORK},
> {quantity : 15}
>
>
> Parent: LOREM IPSUM
>
> Child:
> {productname : FORK},
> {quantity : 25}
>
>
> Actual response when querying for orderid:1 (in the queryeditor in Solr)
>
> (http://localhost:8983/solr/order/select?indent=on&q=orderid:1&wt=json)
>
> {
>   "responseHeader":{
>     "status":0,
>     "QTime":0,
>     "params":{
>       "q":"orderid:1",
>       "indent":"on",
>       "wt":"json",
>       "_":"1485913597768"}},
>   "response":{"numFound":3,"start":0,"docs":[
>       {
>         "orderlineid":1,
>         "orderid":1,
>         "quantity":10,
>         "productname":"KNIFE"},
>       {
>         "orderlineid":2,
>         "orderid":1,
>         "quantity":15,
>         "productname":"FORK"},
>       {
>         "orderlineid":3,
>         "orderid":1,
>         "quantity":12,
>         "quantity":"SPOON"},
>       {
>         "orderid":1,
>         "customername":"ACME",
>         "_version_":1558094660321148928}]
>   }}
>
> Don't see the _child_ marker here, so it doesn't seems like what I have
> seen other people get in the response.
>
> 1) What is wrong with my configuration? How should it be?
> There is a relationship between order and orderline, and that is the order
> id, which is defined as a uniqueKey in managed-schema.xml
> 2) How can I get the customer name, product name and quantity when
> searching either for customer name, or product name? For instance, which
> customer bought FORKS?
> 3) How to use or append either GrapQuery or BlockJoin to give me back the
> result I want?
>
> Please advice
>
> Regards
> Kent
>
>
>
> solrconfig.xml
> ----------------------
>
> <!-- Necessary libs -->
> <lib
> dir="${solr.install.dir:../../../..}/contrib/dataimporthandler-extras/lib"
> regex=".*\.jar" />
> <lib dir="${solr.install.dir:../../../..}/dist/"
> regex="solr-dataimporthandler-\d.*\.jar" />
> ...
>
> <!-- The requesthandler -->
> <requestHandler name="/dataimport"
> class="org.apache.solr.handler.dataimport.DataImportHandler">
>     <lst name="defaults">
>       <str name="config">data-config.xml</str>
>     </lst>
> </requestHandler>
>
>
>
> data-config.xml
> --------------------------
> <dataConfig>
>
>    <!-- Removed the datasource config -->
>    <dataSource driver="" url="" user="" password=""/>
>
>     <document name="orders">
>         <entity name="order" rootEntity='true' query="select orderid,
> customername from ORDER">
>
>             <field column="ORDERID" name="orderid" />
>             <field column="CUSTOMERNAME" name="customername" />
>
>             <entity name="orderline" child="true"
>                 query="select ol.orderlineid, ol.orderid, ol.productname,
> ol.quantity from ORDERLINE ol where ol.orderid =  ${order.orderid}">
>
>                 <field column="ORDERID" name="orderid" />
>                 <field column="ORDERLINEID" name="orderlineid" />
>                 <field column="PRODUCTNAME" name="productname" />
>                 <field column="QUANTITY" name="quantity" />
>             </entity>
>     </entity>
>     </document>
> </dataConfig>
>
>
> managed-data.xml
> --------------------------
>
> <?xml version="1.0" encoding="UTF-8" ?>
>
> <schema name="order-and-orderlines-example" version="1.6">
>
>     <field name="_version_"     type="long"         indexed="false"
> stored="false"/>
>     <field name="_root_"        type="string"       indexed="true"
>  stored="false" docValues="false" />
>     <field name="_text_"        type="text_general" indexed="true"
>  stored="false" multiValued="true"/>
>
> <!-- fields for order and orderlines -->
>     <field name="orderid"       type="long"   indexed="true"  stored="true"
>  multiValued="false" />
>     <field name="orderlineid"   type="long"   indexed="true"  stored="true"
>  multiValued="false" />
>     <field name="customername"  type="string" indexed="true"  stored="true"
>  multiValued="false" />
>     <field name="productname"   type="string" indexed="true"  stored="true"
>  multiValued="false" />
>     <field name="quantity"      type="long"   indexed="false" stored="true"
> multiValued="false" />
>
>
>
>     <!-- Only enabled in the "schemaless" data-driven example (assuming the
> client
>          does not know what fields may be searched) because it's very
> expensive to index everything twice. -->
>     <copyField source="*" dest="_text_"/>
>
>     <uniqueKey>orderid</uniqueKey>
>
>         <fieldType name="string" class="solr.StrField"
> sortMissingLast="true" docValues="true" />
>     <fieldType name="strings" class="solr.StrField" sortMissingLast="true"
> multiValued="true" docValues="true" />
>
>     <!-- boolean type: "true" or "false" -->
>     <fieldType name="boolean" class="solr.BoolField"
> sortMissingLast="true"/>
>
>     <fieldType name="booleans" class="solr.BoolField"
> sortMissingLast="true" multiValued="true"/>
>
>     <!-- sortMissingLast and sortMissingFirst attributes are optional
> attributes are
>          currently supported on types that are sorted internally as strings
>          and on numeric types.
>        This includes "string","boolean", and, as of 3.5 (and 4.x),
>        int, float, long, date, double, including the "Trie" variants.
>        - If sortMissingLast="true", then a sort on this field will cause
> documents
>          without the field to come after documents with the field,
>          regardless of the requested sort order (asc or desc).
>        - If sortMissingFirst="true", then a sort on this field will cause
> documents
>          without the field to come before documents with the field,
>          regardless of the requested sort order.
>        - If sortMissingLast="false" and sortMissingFirst="false" (the
> default),
>          then default lucene sorting will be used which places docs without
> the
>          field first in an ascending sort and last in a descending sort.
>     -->
>
>     <!--
>       Default numeric field types. For faster range queries, consider the
> tint/tfloat/tlong/tdouble types.
>
>       These fields support doc values, but they require the field to be
>       single-valued and either be required or have a default value.
>     -->
>     <fieldType name="int" class="solr.TrieIntField" docValues="true"
> precisionStep="0" positionIncrementGap="0"/>
>     <fieldType name="float" class="solr.TrieFloatField" docValues="true"
> precisionStep="0" positionIncrementGap="0"/>
>     <fieldType name="long" class="solr.TrieLongField" docValues="true"
> precisionStep="0" positionIncrementGap="0"/>
>     <fieldType name="double" class="solr.TrieDoubleField" docValues="true"
> precisionStep="0" positionIncrementGap="0"/>
>
>     <fieldType name="ints" class="solr.TrieIntField" docValues="true"
> precisionStep="0" positionIncrementGap="0" multiValued="true"/>
>     <fieldType name="floats" class="solr.TrieFloatField" docValues="true"
> precisionStep="0" positionIncrementGap="0" multiValued="true"/>
>     <fieldType name="longs" class="solr.TrieLongField" docValues="true"
> precisionStep="0" positionIncrementGap="0" multiValued="true"/>
>     <fieldType name="doubles" class="solr.TrieDoubleField" docValues="true"
> precisionStep="0" positionIncrementGap="0" multiValued="true"/>
>
>     <!--
>      Numeric field types that index each value at various levels of
> precision
>      to accelerate range queries when the number of values between the
> range
>      endpoints is large. See the javadoc for NumericRangeQuery for internal
>      implementation details.
>
>      Smaller precisionStep values (specified in bits) will lead to more
> tokens
>      indexed per value, slightly larger index size, and faster range
> queries.
>      A precisionStep of 0 disables indexing at different precision levels.
>     -->
>     <fieldType name="tint" class="solr.TrieIntField" docValues="true"
> precisionStep="8" positionIncrementGap="0"/>
>     <fieldType name="tfloat" class="solr.TrieFloatField" docValues="true"
> precisionStep="8" positionIncrementGap="0"/>
>     <fieldType name="tlong" class="solr.TrieLongField" docValues="true"
> precisionStep="8" positionIncrementGap="0"/>
>     <fieldType name="tdouble" class="solr.TrieDoubleField" docValues="true"
> precisionStep="8" positionIncrementGap="0"/>
>
>     <fieldType name="tints" class="solr.TrieIntField" docValues="true"
> precisionStep="8" positionIncrementGap="0" multiValued="true"/>
>     <fieldType name="tfloats" class="solr.TrieFloatField" docValues="true"
> precisionStep="8" positionIncrementGap="0" multiValued="true"/>
>     <fieldType name="tlongs" class="solr.TrieLongField" docValues="true"
> precisionStep="8" positionIncrementGap="0" multiValued="true"/>
>     <fieldType name="tdoubles" class="solr.TrieDoubleField"
> docValues="true" precisionStep="8" positionIncrementGap="0"
> multiValued="true"/>
>
>     <!-- The format for this date field is of the form
> 1995-12-31T23:59:59Z, and
>          is a more restricted form of the canonical representation of
> dateTime
>          http://www.w3.org/TR/xmlschema-2/#dateTime
>          The trailing "Z" designates UTC time and is mandatory.
>          Optional fractional seconds are allowed: 1995-12-31T23:59:59.999Z
>          All other components are mandatory.
>
>          Expressions can also be used to denote calculations that should be
>          performed relative to "NOW" to determine the value, ie...
>
>                NOW/HOUR
>                   ... Round to the start of the current hour
>                NOW-1DAY
>                   ... Exactly 1 day prior to now
>                NOW/DAY+6MONTHS+3DAYS
>                   ... 6 months and 3 days in the future from the start of
>                       the current day
>
>          Consult the TrieDateField javadocs for more information.
>
>          Note: For faster range queries, consider the tdate type
>       -->
>     <fieldType name="date" class="solr.TrieDateField" docValues="true"
> precisionStep="0" positionIncrementGap="0"/>
>     <fieldType name="dates" class="solr.TrieDateField" docValues="true"
> precisionStep="0" positionIncrementGap="0" multiValued="true"/>
>
>     <!-- A Trie based date field for faster date range queries and date
> faceting. -->
>     <fieldType name="tdate" class="solr.TrieDateField" docValues="true"
> precisionStep="6" positionIncrementGap="0"/>
>
>     <fieldType name="tdates" class="solr.TrieDateField" docValues="true"
> precisionStep="6" positionIncrementGap="0" multiValued="true"/>
>
>
>     <!--Binary data type. The data should be sent/retrieved in as Base64
> encoded Strings -->
>     <fieldType name="binary" class="solr.BinaryField"/>
>
>     <!-- The "RandomSortField" is not used to store or search any
>          data.  You can declare fields of this type it in your schema
>          to generate pseudo-random orderings of your docs for sorting
>          or function purposes.  The ordering is generated based on the
> field
>          name and the version of the index. As long as the index version
>          remains unchanged, and the same field name is reused,
>          the ordering of the docs will be consistent.
>          If you want different psuedo-random orderings of documents,
>          for the same version of the index, use a dynamicField and
>          change the field name in the request.
>      -->
>     <fieldType name="random" class="solr.RandomSortField" indexed="true" />
>
>     <!-- solr.TextField allows the specification of custom text analyzers
>          specified as a tokenizer and a list of token filters. Different
>          analyzers may be specified for indexing and querying.
>
>          The optional positionIncrementGap puts space between multiple
> fields of
>          this type on the same document, with the purpose of preventing
> false phrase
>          matching across fields.
>
>          For more info on customizing your analyzer chain, please see
>          http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters
>      -->
>
>     <!-- One can also specify an existing Analyzer class that has a
>          default constructor via the class attribute on the analyzer
> element.
>          Example:
>     <fieldType name="text_greek" class="solr.TextField">
>       <analyzer class="org.apache.lucene.analysis.el.GreekAnalyzer"/>
>     </fieldType>
>     -->
>
>     <!-- A text field that only splits on whitespace for exact matching of
> words -->
>     <dynamicField name="*_ws" type="text_ws"  indexed="true"
>  stored="true"/>
>     <fieldType name="text_ws" class="solr.TextField"
> positionIncrementGap="100">
>       <analyzer>
>         <tokenizer class="solr.WhitespaceTokenizerFactory"/>
>       </analyzer>
>     </fieldType>
>
>     <!-- A general text field that has reasonable, generic
>          cross-language defaults: it tokenizes with StandardTokenizer,
>          removes stop words from case-insensitive "stopwords.txt"
>          (empty by default), and down cases.  At query time only, it
>          also applies synonyms.
>     -->
>     <fieldType name="text_general" class="solr.TextField"
> positionIncrementGap="100" multiValued="true">
>       <analyzer type="index">
>         <tokenizer class="solr.StandardTokenizerFactory"/>
>         <filter class="solr.StopFilterFactory" ignoreCase="true"
> words="stopwords.txt" />
>         <!-- in this example, we will only use synonyms at query time
>         <filter class="solr.SynonymFilterFactory"
> synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
>         -->
>         <filter class="solr.LowerCaseFilterFactory"/>
>       </analyzer>
>       <analyzer type="query">
>         <tokenizer class="solr.StandardTokenizerFactory"/>
>         <filter class="solr.StopFilterFactory" ignoreCase="true"
> words="stopwords.txt" />
>         <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"
> ignoreCase="true" expand="true"/>
>         <filter class="solr.LowerCaseFilterFactory"/>
>       </analyzer>
>     </fieldType>
>
>     <!-- A text field with defaults appropriate for English: it
>          tokenizes with StandardTokenizer, removes English stop words
>          (lang/stopwords_en.txt), down cases, protects words from
> protwords.txt, and
>          finally applies Porter's stemming.  The query time analyzer
>          also applies synonyms from synonyms.txt. -->
>     <dynamicField name="*_txt_en" type="text_en"  indexed="true"
>  stored="true"/>
>     <fieldType name="text_en" class="solr.TextField"
> positionIncrementGap="100">
>       <analyzer type="index">
>         <tokenizer class="solr.StandardTokenizerFactory"/>
>         <!-- in this example, we will only use synonyms at query time
>         <filter class="solr.SynonymFilterFactory"
> synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
>         -->
>         <!-- Case insensitive stop word removal.
>         -->
>         <filter class="solr.StopFilterFactory"
>                 ignoreCase="true"
>                 words="lang/stopwords_en.txt"
>             />
>         <filter class="solr.LowerCaseFilterFactory"/>
>         <filter class="solr.EnglishPossessiveFilterFactory"/>
>         <filter class="solr.KeywordMarkerFilterFactory"
> protected="protwords.txt"/>
>         <!-- Optionally you may want to use this less aggressive stemmer
> instead of PorterStemFilterFactory:
>         <filter class="solr.EnglishMinimalStemFilterFactory"/>
>         -->
>         <filter class="solr.PorterStemFilterFactory"/>
>       </analyzer>
>       <analyzer type="query">
>         <tokenizer class="solr.StandardTokenizerFactory"/>
>         <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"
> ignoreCase="true" expand="true"/>
>         <filter class="solr.StopFilterFactory"
>                 ignoreCase="true"
>                 words="lang/stopwords_en.txt"
>         />
>         <filter class="solr.LowerCaseFilterFactory"/>
>         <filter class="solr.EnglishPossessiveFilterFactory"/>
>         <filter class="solr.KeywordMarkerFilterFactory"
> protected="protwords.txt"/>
>         <!-- Optionally you may want to use this less aggressive stemmer
> instead of PorterStemFilterFactory:
>         <filter class="solr.EnglishMinimalStemFilterFactory"/>
>         -->
>         <filter class="solr.PorterStemFilterFactory"/>
>       </analyzer>
>     </fieldType>
>
>     <!-- A text field with defaults appropriate for English, plus
>          aggressive word-splitting and autophrase features enabled.
>          This field is just like text_en, except it adds
>          WordDelimiterFilter to enable splitting and matching of
>          words on case-change, alpha numeric boundaries, and
>          non-alphanumeric chars.  This means certain compound word
>          cases will work, for example query "wi fi" will match
>          document "WiFi" or "wi-fi".
>     -->
>     <dynamicField name="*_txt_en_split" type="text_en_splitting"
>  indexed="true"  stored="true"/>
>     <fieldType name="text_en_splitting" class="solr.TextField"
> positionIncrementGap="100" autoGeneratePhraseQueries="true">
>       <analyzer type="index">
>         <tokenizer class="solr.WhitespaceTokenizerFactory"/>
>         <!-- in this example, we will only use synonyms at query time
>         <filter class="solr.SynonymFilterFactory"
> synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
>         -->
>         <!-- Case insensitive stop word removal.
>         -->
>         <filter class="solr.StopFilterFactory"
>                 ignoreCase="true"
>                 words="lang/stopwords_en.txt"
>         />
>         <filter class="solr.WordDelimiterFilterFactory"
> generateWordParts="1" generateNumberParts="1" catenateWords="1"
> catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
>         <filter class="solr.LowerCaseFilterFactory"/>
>         <filter class="solr.KeywordMarkerFilterFactory"
> protected="protwords.txt"/>
>         <filter class="solr.PorterStemFilterFactory"/>
>       </analyzer>
>       <analyzer type="query">
>         <tokenizer class="solr.WhitespaceTokenizerFactory"/>
>         <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"
> ignoreCase="true" expand="true"/>
>         <filter class="solr.StopFilterFactory"
>                 ignoreCase="true"
>                 words="lang/stopwords_en.txt"
>         />
>         <filter class="solr.WordDelimiterFilterFactory"
> generateWordParts="1" generateNumberParts="1" catenateWords="0"
> catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
>         <filter class="solr.LowerCaseFilterFactory"/>
>         <filter class="solr.KeywordMarkerFilterFactory"
> protected="protwords.txt"/>
>         <filter class="solr.PorterStemFilterFactory"/>
>       </analyzer>
>     </fieldType>
>
>     <!-- Less flexible matching, but less false matches.  Probably not
> ideal for product names,
>          but may be good for SKUs.  Can insert dashes in the wrong place
> and still match. -->
>     <dynamicField name="*_txt_en_split_tight"
> type="text_en_splitting_tight"  indexed="true"  stored="true"/>
>     <fieldType name="text_en_splitting_tight" class="solr.TextField"
> positionIncrementGap="100" autoGeneratePhraseQueries="true">
>       <analyzer>
>         <tokenizer class="solr.WhitespaceTokenizerFactory"/>
>         <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"
> ignoreCase="true" expand="false"/>
>         <filter class="solr.StopFilterFactory" ignoreCase="true"
> words="lang/stopwords_en.txt"/>
>         <filter class="solr.WordDelimiterFilterFactory"
> generateWordParts="0" generateNumberParts="0" catenateWords="1"
> catenateNumbers="1" catenateAll="0"/>
>         <filter class="solr.LowerCaseFilterFactory"/>
>         <filter class="solr.KeywordMarkerFilterFactory"
> protected="protwords.txt"/>
>         <filter class="solr.EnglishMinimalStemFilterFactory"/>
>         <!-- this filter can remove any duplicate tokens that appear at the
> same position - sometimes
>              possible with WordDelimiterFilter in conjuncton with stemming.
> -->
>         <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
>       </analyzer>
>     </fieldType>
>
>     <!-- Just like text_general except it reverses the characters of
>          each token, to enable more efficient leading wildcard queries.
>     -->
>     <dynamicField name="*_txt_rev" type="text_general_rev"  indexed="true"
>  stored="true"/>
>     <fieldType name="text_general_rev" class="solr.TextField"
> positionIncrementGap="100">
>       <analyzer type="index">
>         <tokenizer class="solr.StandardTokenizerFactory"/>
>         <filter class="solr.StopFilterFactory" ignoreCase="true"
> words="stopwords.txt" />
>         <filter class="solr.LowerCaseFilterFactory"/>
>         <filter class="solr.ReversedWildcardFilterFactory"
> withOriginal="true"
>                 maxPosAsterisk="3" maxPosQuestion="2"
> maxFractionAsterisk="0.33"/>
>       </analyzer>
>       <analyzer type="query">
>         <tokenizer class="solr.StandardTokenizerFactory"/>
>         <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"
> ignoreCase="true" expand="true"/>
>         <filter class="solr.StopFilterFactory" ignoreCase="true"
> words="stopwords.txt" />
>         <filter class="solr.LowerCaseFilterFactory"/>
>       </analyzer>
>     </fieldType>
>
>     <dynamicField name="*_phon_en" type="phonetic_en"  indexed="true"
>  stored="true"/>
>     <fieldType name="phonetic_en" stored="false" indexed="true"
> class="solr.TextField" >
>       <analyzer>
>         <tokenizer class="solr.StandardTokenizerFactory"/>
>         <filter class="solr.DoubleMetaphoneFilterFactory" inject="false"/>
>       </analyzer>
>     </fieldType>
>
>     <!-- lowercases the entire field value, keeping it as a single token.
>  -->
>     <dynamicField name="*_s_lower" type="lowercase"  indexed="true"
>  stored="true"/>
>     <fieldType name="lowercase" class="solr.TextField"
> positionIncrementGap="100">
>       <analyzer>
>         <tokenizer class="solr.KeywordTokenizerFactory"/>
>         <filter class="solr.LowerCaseFilterFactory" />
>       </analyzer>
>     </fieldType>
>
>     <!--
>       Example of using PathHierarchyTokenizerFactory at index time, so
>       queries for paths match documents at that path, or in descendent
> paths
>     -->
>     <dynamicField name="*_descendent_path" type="descendent_path"
>  indexed="true"  stored="true"/>
>     <fieldType name="descendent_path" class="solr.TextField">
>       <analyzer type="index">
>         <tokenizer class="solr.PathHierarchyTokenizerFactory"
> delimiter="/"
> />
>       </analyzer>
>       <analyzer type="query">
>         <tokenizer class="solr.KeywordTokenizerFactory" />
>       </analyzer>
>     </fieldType>
>
>     <!--
>       Example of using PathHierarchyTokenizerFactory at query time, so
>       queries for paths match documents at that path, or in ancestor paths
>     -->
>     <dynamicField name="*_ancestor_path" type="ancestor_path"
>  indexed="true"  stored="true"/>
>     <fieldType name="ancestor_path" class="solr.TextField">
>       <analyzer type="index">
>         <tokenizer class="solr.KeywordTokenizerFactory" />
>       </analyzer>
>       <analyzer type="query">
>         <tokenizer class="solr.PathHierarchyTokenizerFactory"
> delimiter="/"
> />
>       </analyzer>
>     </fieldType>
>
>     <!-- since fields of this type are by default not stored or indexed,
>          any data added to them will be ignored outright.  -->
>     <fieldType name="ignored" stored="false" indexed="false"
> docValues="false" multiValued="true" class="solr.StrField" />
>
>     <!-- This point type indexes the coordinates as separate fields
> (subFields)
>       If subFieldType is defined, it references a type, and a dynamic field
>       definition is created matching *___<typename>.  Alternately, if
>       subFieldSuffix is defined, that is used to create the subFields.
>       Example: if subFieldType="double", then the coordinates would be
>         indexed in fields myloc_0___double,myloc_1___double.
>       Example: if subFieldSuffix="_d" then the coordinates would be indexed
>         in fields myloc_0_d,myloc_1_d
>       The subFields are an implementation detail of the fieldType, and end
>       users normally should not need to know about them.
>      -->
>     <dynamicField name="*_point" type="point"  indexed="true"
>  stored="true"/>
>     <fieldType name="point" class="solr.PointType" dimension="2"
> subFieldSuffix="_d"/>
>
>     <!-- A specialized field for geospatial search. If indexed, this
> fieldType must not be multivalued. -->
>     <fieldType name="location" class="solr.LatLonType"
> subFieldSuffix="_coordinate"/>
>
>     <!-- An alternative geospatial field type new to Solr 4.  It supports
> multiValued and polygon shapes.
>       For more information about this and other Spatial fields new to Solr
> 4, see:
>       http://wiki.apache.org/solr/SolrAdaptersForLuceneSpatial4
>     -->
>     <fieldType name="location_rpt"
> class="solr.SpatialRecursivePrefixTreeFieldType"
>                geo="true" distErrPct="0.025" maxDistErr="0.001"
> distanceUnits="kilometers" />
>
>     <!-- Money/currency field type. See
> http://wiki.apache.org/solr/MoneyFieldType
>         Parameters:
>           defaultCurrency: Specifies the default currency if none
> specified. Defaults to "USD"
>           precisionStep:   Specifies the precisionStep for the TrieLong
> field used for the amount
>           providerClass:   Lets you plug in other exchange provider
> backend:
>                            solr.FileExchangeRateProvider is the default and
> takes one parameter:
>                              currencyConfig: name of an xml file holding
> exchange rates
>                            solr.OpenExchangeRatesOrgProvider uses rates
> from openexchangerates.org:
>                              ratesFileLocation: URL or path to rates JSON
> file (default latest.json on the web)
>                              refreshInterval: Number of minutes between
> each rates fetch (default: 1440, min: 60)
>     -->
>     <fieldType name="currency" class="solr.CurrencyField" precisionStep="8"
> defaultCurrency="USD" currencyConfig="currency.xml" />
>
> </schema>
>