Have you checked https://cwiki.apache.org/confluence/display/solr/Other+Parsers#OtherParsers-BlockJoinQueryParsers ?
01 февр. 2017 г. 10:42 пользователь "Kent Iversen" <kent.iver...@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> >