如何实现Solr Facet含分数与小数的字母数字排序?
To get the correct natural numeric order (including fractions like 3/4 = 0.75 sitting between 0.7 and 0.8), you need to convert all your mixed-format numeric strings into a standardized floating-point value at index time, then use this numeric field for sorting. Here's a step-by-step approach tailored to your use case:
1. Add a Numeric Field to Your Schema
First, define a new field in your schema (either schema.xml or managed schema) to store the parsed numeric value. A float type works perfectly for size-related data:
<field name="numeric_size" type="float" indexed="true" stored="true"/>
2. Use a Script Update Processor to Parse Values at Index Time
Write a script that parses your original size field (e.g., size) and converts its mixed-format value to a float. This handles decimals, pure fractions, and mixed numbers like 1 1/2.
Example Groovy Script (for ScriptUpdateProcessor)
Create a file parse_size.groovy in your Solr core's conf/scripts directory with this logic:
def originalSize = doc.getFieldValue("size") if (originalSize) { // Extract the numeric portion (strip off the unit like "inch/inches") def numPart = originalSize.split(/\s+/)[0..-2].join(" ").trim() float parsedValue = 0.0 try { if (numPart.contains(" ")) { // Handle mixed numbers (e.g., "1 1/2" = 1 + 0.5 = 1.5) def parts = numPart.split(" ") def intPart = Float.parseFloat(parts[0]) def fraction = parts[1].split("/") def numerator = Float.parseFloat(fraction[0]) def denominator = Float.parseFloat(fraction[1]) if (denominator != 0) { parsedValue = intPart + (numerator / denominator) } } else if (numPart.contains("/")) { // Handle pure fractions (e.g., "3/4" = 0.75) def fraction = numPart.split("/") def numerator = Float.parseFloat(fraction[0]) def denominator = Float.parseFloat(fraction[1]) if (denominator != 0) { parsedValue = numerator / denominator } } else { // Handle decimals or integers (e.g., "0.7", "11") parsedValue = Float.parseFloat(numPart) } // Add the parsed value to the numeric field doc.addField("numeric_size", parsedValue) } catch (NumberFormatException e) { // Log invalid values for debugging log.error("Failed to parse size value: ${originalSize}", e) } }
3. Configure the Update Chain
Update your solrconfig.xml to add an update chain that runs this script during indexing:
<updateProcessor name="parseSizeScript" class="solr.ScriptUpdateProcessorFactory"> <str name="script">parse_size.groovy</str> </updateProcessor> <updateChain name="sizeParsingChain"> <processor class="parseSizeScript"/> <processor class="solr.RunUpdateProcessorFactory"/> </updateChain> <!-- Set as default update chain for all index requests --> <initParams path="/update/**"> <lst name="defaults"> <str name="update.chain">sizeParsingChain</str> </lst> </initParams>
4. Sort Facets Using the Numeric Field
When querying for facets, tell Solr to sort the facet values using your numeric_size field. Add these parameters to your API request:
facet=true&facet.field=size&facet.sort=field&facet.sort.field=numeric_size&facet.sort.order=asc
facet.sort=field: Tells Solr to sort facets by a specified fieldfacet.sort.field=numeric_size: Specifies the numeric field to use for sortingfacet.sort.order=asc: Ensures ascending order (smallest to largest)
Key Notes
- Unit Consistency: This assumes all values use the same unit (e.g., inches). If you have mixed units, add logic to convert to a standard unit before storing the numeric value.
- Reindexing: After setting up the processor, reindex all documents to populate the
numeric_sizefield. - Error Handling: The script includes basic error handling for invalid values—adjust based on your data quality needs.
This approach will give you the exact order you want: 0.7 inch → 3/4 inch → 0.8 inch → 1 1/2 inches → 2 inches → 11 inches
内容的提问来源于stack exchange,提问作者Yirmiyahu Fischer

