Solr 概述 什么是 Solr Apache Solr 是一个基于 Lucene 的企业级搜索服务器, 提供了全文搜索、 命中高亮、 分面搜索、 动态聚类、 数据库集成等功能。
核心功能
全文搜索: 支持复杂的全文检索
分面搜索: 多维度分类统计
高亮显示: 搜索结果关键词高亮
拼写检查: 自动纠正拼写错误
更多类似: 推荐相似文档
主要优势
成熟稳定: 经过多年企业级应用验证
功能丰富: 内置多种搜索功能
易于扩展: 支持插件机制
管理界面: 提供 Web 管理控制台
Solr vs Elasticsearch
特性
Solr
Elasticsearch
实时性
近实时( NRT)
近实时( NRT)
分布式
支持( SolrCloud)
原生支持
查询语言
丰富的查询语法
DSL( JSON)
适用场景
传统搜索、 静态数据
日志分析、 实时数据
社区活跃度
较低
非常高
学习曲线
较陡
相对平缓
1 2 3 4 细节注意: 1. Solr 适合传统的搜索场景, 如电商商品搜索 2. Elasticsearch 更适合日志分析、 实时监控等场景 3. 两者都基于 Lucene, 核心原理相似
Solr 的核心概念 基本概念
Core( 核心)
Document( 文档)
Field( 字段)
Schema( 模式)
Index( 索引)
架构组件
SolrCloud
ZooKeeper
Shard( 分片)
Replica( 副本)
Solr 的工作原理 索引流程 1 2 3 4 5 1. 客户端发送文档到 Solr 2. Solr 解析文档并提取字段 3. 对文本字段进行分词处理 4. 构建倒排索引 5. 提交索引到磁盘
搜索流程 1 2 3 4 5 1. 客户端发送查询请求 2. Solr 解析查询语句 3. 在倒排索引中查找匹配的文档 4. 计算相关度评分 5. 排序并返回结果
环境搭建 安装 Solr Docker 安装( 推荐) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 docker pull solr:8.11.0 docker run -d \ --name solr \ -p 8983:8983 \ solr:8.11.0 docker exec -it solr solr create_core -c mycore
Linux 安装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 wget https://archive.apache.org/dist/lucene/solr/8.11.0/solr-8.11.0.tgz tar -xzf solr-8.11.0.tgz cd solr-8.11.0./bin/solr start ./bin/solr create -c mycore ./bin/solr stop -all
Windows 安装
下载地址: https://lucene.apache.org/solr/downloads.html
步骤:
下载压缩包并解压
进入 bin 目录
运行 solr.cmd start
创建 Core: solr.cmd create -c mycore
macOS 安装 1 2 3 4 5 6 7 8 brew install solr brew services start solr solr create -c mycore
目录结构 1 2 3 4 5 6 7 8 9 10 11 12 solr-8.11.0/ ├── bin/ # 可执行脚本 ├── server/ # 服务器文件 │ ├── solr/ # Solr 主目录 │ │ └── mycore/ # Core 目录 │ │ ├── conf/ # 配置文件 │ │ │ ├── solrconfig.xml │ │ │ └── schema.xml │ │ └── data/ # 索引数据 │ └── logs/ # 日志文件 ├── example/ # 示例文件 └── docs/ # 文档
验证安装 1 2 3 4 5 6 7 8 curl http://localhost:8983/solr/admin/info/system?wt=json curl http://localhost:8983/solr/admin/cores?action=STATUS&wt=json
基本操作 Core 操作 创建 Core 1 2 3 4 5 6 7 8 solr create -c products curl "http://localhost:8983/solr/admin/cores?action=CREATE&name=products&instanceDir=products" solr create -c products -d basic_configs
查看 Core 1 2 3 4 5 curl http://localhost:8983/solr/admin/cores?action=STATUS&wt=json curl http://localhost:8983/solr/products/admin/ping?wt=json
删除 Core 1 2 3 4 5 solr delete -c products curl "http://localhost:8983/solr/admin/cores?action=UNLOAD&core=products&deleteIndex=true&deleteDataDir=true&deleteInstanceDir=true"
重载 Core 1 curl "http://localhost:8983/solr/admin/cores?action=RELOAD&core=products"
文档操作 添加文档 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 curl -X POST "http://localhost:8983/solr/products/update?commit=true" \ -H 'Content-Type: application/json' \ -d '[ { "id": "1", "name": "iPhone 13", "price": 5999, "category": "手机", "brand": "Apple", "description": "苹果手机, A15芯片" } ]' curl -X POST "http://localhost:8983/solr/products/update?commit=true" \ -H 'Content-Type: application/json' \ -d '[ {"id": "2", "name": "华为Mate40", "price": 4999, "category": "手机", "brand": "华为"}, {"id": "3", "name": "小米11", "price": 3999, "category": "手机", "brand": "小米"} ]' curl -X POST "http://localhost:8983/solr/products/update?commit=true" \ -H 'Content-Type: text/xml' \ -d '<add> <doc> <field name="id">4</field> <field name="name">OPPO Find X3</field> <field name="price">4499</field> </doc> </add>'
查询文档 1 2 3 4 5 6 7 8 9 10 11 curl "http://localhost:8983/solr/products/select?q=*:*&wt=json" curl "http://localhost:8983/solr/products/select?q=name:iPhone&wt=json" curl "http://localhost:8983/solr/products/select?q=*:*&start=0&rows=10&wt=json" curl "http://localhost:8983/solr/products/select?q=*:*&sort=price desc&wt=json"
更新文档 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 curl -X POST "http://localhost:8983/solr/products/update?commit=true" \ -H 'Content-Type: application/json' \ -d '[ { "id": "1", "name": "iPhone 13 Pro", "price": 7999 } ]' curl -X POST "http://localhost:8983/solr/products/update?commit=true" \ -H 'Content-Type: application/json' \ -d '[ { "id": "1", "price": {"set": 6999} } ]' curl -X POST "http://localhost:8983/solr/products/update?commit=true" \ -H 'Content-Type: application/json' \ -d '[ { "id": "1", "price": {"inc": 100} } ]'
删除文档 1 2 3 4 5 6 7 8 9 10 11 12 13 14 curl -X POST "http://localhost:8983/solr/products/update?commit=true" \ -H 'Content-Type: application/json' \ -d '{"delete": {"id": "1"}}' curl -X POST "http://localhost:8983/solr/products/update?commit=true" \ -H 'Content-Type: application/json' \ -d '{"delete": {"query": "brand:Apple"}}' curl -X POST "http://localhost:8983/solr/products/update?commit=true" \ -H 'Content-Type: application/json' \ -d '{"delete": {"query": "*:*"}}'
Schema 设计 字段类型
类型
说明
示例
string
字符串, 不分词
"ABC123"
text_general
文本, 会分词
"Hello World"
tint
整数
42
tlong
长整数
9223372036854775807
tfloat
浮点数
3.14
tdouble
双精度
3.1415926
tdate
日期
"2024-01-01T00:00:00Z"
boolean
布尔值
true/false
location
地理位置
"39.9042,116.4074"
配置 Schema 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <schema name ="products" version ="1.6" > <uniqueKey > id</uniqueKey > <fields > <field name ="id" type ="string" indexed ="true" stored ="true" required ="true" /> <field name ="name" type ="text_ik" indexed ="true" stored ="true" /> <field name ="price" type ="tint" indexed ="true" stored ="true" /> <field name ="category" type ="string" indexed ="true" stored ="true" /> <field name ="brand" type ="string" indexed ="true" stored ="true" /> <field name ="description" type ="text_ik" indexed ="true" stored ="false" /> <field name ="create_time" type ="tdate" indexed ="true" stored ="true" /> </fields > <copyField source ="name" dest ="text" /> <copyField source ="description" dest ="text" /> <dynamicField name ="*_s" type ="string" indexed ="true" stored ="true" /> <dynamicField name ="*_i" type ="tint" indexed ="true" stored ="true" /> <dynamicField name ="*_t" type ="text_ik" indexed ="true" stored ="true" /> </schema >
字段属性
属性
说明
默认值
indexed
是否建立索引
false
stored
是否存储原始值
false
required
是否必填
false
multiValued
是否多值
false
docValues
是否启用列缓存
false
查询语法 基本查询 简单查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 q=*:* q=name:iPhone q=name:"iPhone 13" q=name:iPh* q=name:?Phone q=price:[1000 TO 5000] q=price:{1000 TO 5000}
布尔查询 1 2 3 4 5 6 7 8 9 10 11 q=name:iPhone AND brand:Apple q=name:iPhone OR name:Huawei q=name:iPhone NOT brand:Samsung q=(name:iPhone OR name:Huawei) AND price:[3000 TO 8000]
字段查询 1 2 3 4 5 6 7 8 9 10 11 q=name:iPhone q=(name:iPhone OR description:苹果) q=iPhone q=-brand:Samsung
高级查询 模糊查询 1 2 3 4 5 6 q=name:iphon~1 q=name:iphon~2 q=name:"iPhone 13" ~0.8
正则查询 1 2 q=name:/i[ph]+one/ q=email:/.*@example\.com/
邻近查询
提升权重 1 2 q=name:iPhone^2 OR description:苹果^0.5
特殊查询 存在查询 1 2 3 4 5 q=_exists_:price q=-_exists_:discount
分组查询 1 2 facet=true &facet.field=brand&facet.field=category
查询参数 常用参数
参数
说明
示例
q
查询语句
q=name:iPhone
fq
过滤查询
fq=price:[1000 TO 5000]
sort
排序
sort=price desc
start
起始位置
start=0
rows
返回条数
rows=10
fl
返回字段
fl=id,name,price
df
默认字段
df=name
wt
响应格式
wt=json
完整查询示例 1 2 3 4 5 6 7 8 curl "http://localhost:8983/solr/products/select?\ q=name:iPhone&\ fq=price:[3000 TO 8000]&\ sort=price desc&\ start=0&\ rows=10&\ fl=id,name,price,brand&\ wt=json"
高亮显示 1 2 3 4 5 6 7 curl "http://localhost:8983/solr/products/select?\ q=name:iPhone&\ hl=true&\ hl.fl=name,description&\ hl.simple.pre=<em>&\ hl.simple.post=</em>&\ wt=json"
分面搜索 1 2 3 4 5 6 7 8 9 10 curl "http://localhost:8983/solr/products/select?\ q=*:*&\ facet=true&\ facet.field=brand&\ facet.field=category&\ facet.range=price&\ f.price.facet.range.start=0&\ f.price.facet.range.end=10000&\ f.price.facet.range.gap=1000&\ wt=json"
Spring Boot 整合 添加依赖 1 2 3 4 5 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-solr</artifactId > </dependency >
配置文件 1 2 3 4 5 spring: data: solr: host: http://localhost:8983/solr
创建实体类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package com.example.entity;import lombok.Data;import org.apache.solr.client.solrj.beans.Field;import org.springframework.data.solr.core.mapping.SolrDocument;import java.math.BigDecimal;import java.time.LocalDateTime;@Data @SolrDocument(solrCoreName = "products") public class Product { @Field private String id; @Field private String name; @Field private BigDecimal price; @Field private String category; @Field private String brand; @Field private String description; @Field private LocalDateTime createTime; }
创建 Repository 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.example.repository;import com.example.entity.Product;import org.springframework.data.domain.Page;import org.springframework.data.domain.Pageable;import org.springframework.data.solr.repository.Query;import org.springframework.data.solr.repository.SolrCrudRepository;import org.springframework.stereotype.Repository;import java.math.BigDecimal;import java.util.List;@Repository public interface ProductRepository extends SolrCrudRepository <Product, String> { List<Product> findByName (String name) ; Page<Product> findByCategory (String category, Pageable pageable) ; List<Product> findByPriceBetween (BigDecimal minPrice, BigDecimal maxPrice) ; @Query("name:?0 AND brand:?1") List<Product> searchByNameAndBrand (String name, String brand) ; @Query("name:?0 OR description:?0") Page<Product> searchByKeyword (String keyword, Pageable pageable) ; }
创建 Service 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 package com.example.service;import com.example.entity.Product;import com.example.repository.ProductRepository;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.domain.Page;import org.springframework.data.domain.PageRequest;import org.springframework.data.solr.core.SolrTemplate;import org.springframework.data.solr.core.query.Criteria;import org.springframework.data.solr.core.query.SimpleQuery;import org.springframework.data.solr.core.query.result.FacetPage;import org.springframework.stereotype.Service;import java.math.BigDecimal;import java.util.List;@Service public class ProductService { @Autowired private ProductRepository productRepository; @Autowired private SolrTemplate solrTemplate; public Product save (Product product) { return productRepository.save(product); } public Iterable<Product> saveAll (List<Product> products) { return productRepository.saveAll(products); } public Product findById (String id) { return productRepository.findById(id).orElse(null ); } public void delete (String id) { productRepository.deleteById(id); } public Page<Product> page (int pageNum, int pageSize) { return productRepository.findAll(PageRequest.of(pageNum - 1 , pageSize)); } public List<Product> search (String keyword) { Criteria criteria = new Criteria ("name" ).contains(keyword) .or(new Criteria ("description" ).contains(keyword)); SimpleQuery query = new SimpleQuery (criteria); return solrTemplate.queryForPage(query, Product.class).getContent(); } public List<Product> findByPriceRange (BigDecimal minPrice, BigDecimal maxPrice) { return productRepository.findByPriceBetween(minPrice, maxPrice); } public FacetPage<Product> facetByCategory () { SimpleQuery query = new SimpleQuery (new Criteria ("*:*" )); query.addFacetOnField("category" ); return solrTemplate.queryForFacetPage(query, Product.class); } }
创建 Controller 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 package com.example.controller;import com.example.entity.Product;import com.example.service.ProductService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.domain.Page;import org.springframework.web.bind.annotation.*;import java.math.BigDecimal;import java.util.List;@RestController @RequestMapping("/products") public class ProductController { @Autowired private ProductService productService; @PostMapping public Product create (@RequestBody Product product) { return productService.save(product); } @PostMapping("/batch") public Iterable<Product> batchCreate (@RequestBody List<Product> products) { return productService.saveAll(products); } @GetMapping("/{id}") public Product get (@PathVariable String id) { return productService.findById(id); } @DeleteMapping("/{id}") public void delete (@PathVariable String id) { productService.delete(id); } @GetMapping("/page") public Page<Product> page ( @RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "10") int pageSize) { return productService.page(pageNum, pageSize); } @GetMapping("/search") public List<Product> search (@RequestParam String keyword) { return productService.search(keyword); } @GetMapping("/price") public List<Product> findByPrice ( @RequestParam BigDecimal minPrice, @RequestParam BigDecimal maxPrice) { return productService.findByPriceRange(minPrice, maxPrice); } }
高级功能 中文分词( IK Analyzer) 安装 IK 分词器
1 2 3 4 5 6 7 8 9 10 11 12 <fieldType name ="text_ik" class ="solr.TextField" > <analyzer type ="index" > <tokenizer class ="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart ="false" /> </analyzer > <analyzer type ="query" > <tokenizer class ="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart ="true" /> </analyzer > </fieldType > <field name ="name" type ="text_ik" indexed ="true" stored ="true" /> <field name ="description" type ="text_ik" indexed ="true" stored ="true" />
拼音分词 1 2 3 4 5 6 7 8 9 10 11 <fieldType name ="text_pinyin" class ="solr.TextField" > <analyzer type ="index" > <tokenizer class ="org.wltea.analyzer.lucene.IKTokenizerFactory" /> <filter class ="com.github.magese.pinyin.PinyinTokenFilterFactory" /> </analyzer > <analyzer type ="query" > <tokenizer class ="org.wltea.analyzer.lucene.IKTokenizerFactory" /> <filter class ="com.github.magese.pinyin.PinyinTokenFilterFactory" /> </analyzer > </fieldType >
拼写检查 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <searchComponent name ="spellcheck" class ="solr.SpellCheckComponent" > <str name ="queryAnalyzerFieldType" > text_ik</str > <lst name ="spellchecker" > <str name ="name" > default</str > <str name ="field" > name</str > <str name ="classname" > solr.DirectSolrSpellChecker</str > <str name ="distanceMeasure" > internal</str > <float name ="accuracy" > 0.5</float > <int name ="maxEdits" > 2</int > <int name ="minPrefix" > 1</int > <int name ="maxInspections" > 5</int > <int name ="minQueryLength" > 4</int > <float name ="maxQueryFrequency" > 0.01</float > </lst > </searchComponent > <requestHandler name ="/spell" class ="solr.SearchHandler" startup ="lazy" > <lst name ="defaults" > <str name ="df" > name</str > <str name ="spellcheck" > true</str > <str name ="spellcheck.extendedResults" > true</str > <str name ="spellcheck.count" > 10</str > <str name ="spellcheck.alternativeTermCount" > 5</str > <str name ="spellcheck.maxResultsForSuggest" > 5</str > <str name ="spellcheck.collate" > true</str > <str name ="spellcheck.collateExtendedResults" > true</str > <str name ="spellcheck.maxCollationTries" > 10</str > <str name ="spellcheck.maxCollations" > 5</str > </lst > <arr name ="last-components" > <str > spellcheck</str > </arr > </requestHandler >
1 2 curl "http://localhost:8983/solr/products/spell?q=iphon&wt=json"
更多类似 1 2 3 4 5 6 7 curl "http://localhost:8983/solr/products/mlt?\ q=id:1&\ mlt.fl=name,description&\ mlt.mindf=1&\ mlt.mintf=1&\ wt=json"
地理位置搜索 1 2 <field name ="location" type ="location" indexed ="true" stored ="true" />
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 curl -X POST "http://localhost:8983/solr/products/update?commit=true" \ -H 'Content-Type: application/json' \ -d '[ { "id": "100", "name": "北京店", "location": "39.9042,116.4074" } ]' curl "http://localhost:8983/solr/products/select?\ q=*:*&\ fq={!geofilt pt=39.9042,116.4074 sfield=location d=10}&\ wt=json"
性能优化 索引优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <autoCommit > <maxTime > 15000</maxTime > <openSearcher > false</openSearcher > </autoCommit > <autoSoftCommit > <maxTime > 1000</maxTime > </autoSoftCommit > <mergePolicy class ="org.apache.lucene.index.TieredMergePolicy" > <int name ="maxMergeAtOnce" > 10</int > <int name ="segmentsPerTier" > 10</int > </mergePolicy >
查询优化 1 2 3 4 5 6 7 8 9 10 11 12 13 Criteria criteria = new Criteria ("category" ).is("手机" );SimpleQuery query = new SimpleQuery (criteria);query.addFilterQuery(new SimpleQuery ( new Criteria ("price" ).between(1000 , 5000 ) )); query.setFields("id" , "name" , "price" ); query.setOffset(0 ); query.setRows(10 );
缓存配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <cache name ="filterCache" class ="solr.FastLRUCache" size ="512" initialSize ="512" autowarmCount ="0" /> <cache name ="queryResultCache" class ="solr.LRUCache" size ="512" initialSize ="512" autowarmCount ="0" /> <cache name ="documentCache" class ="solr.LRUCache" size ="512" initialSize ="512" autowarmCount ="0" />
批量导入 1 2 3 4 5 6 7 8 9 10 11 12 13 14 SolrClient client = new HttpSolrClient .Builder("http://localhost:8983/solr/products" ).build();List<SolrInputDocument> docs = new ArrayList <>(); for (Product product : products) { SolrInputDocument doc = new SolrInputDocument (); doc.addField("id" , product.getId()); doc.addField("name" , product.getName()); doc.addField("price" , product.getPrice()); docs.add(doc); } client.add(docs); client.commit();
最佳实践 命名规范 1 2 3 4 5 6 7 8 9 10 Core 命名: - 小写字母 - 使用下划线或连字符 - 语义化命名 - 示例: product_index、 user_search 字段命名: - 使用驼峰命名 - 类型后缀: _s(string)、 _i(int)、 _t(text) - 示例: productName、 price_i、 description_t
Schema 设计建议 1 2 3 4 5 6 7 8 9 10 11 <field name ="id" type ="string" indexed ="true" stored ="true" /> <field name ="name" type ="text_ik" indexed ="true" stored ="true" /> <field name ="price" type ="tint" indexed ="true" stored ="true" docValues ="true" /> <copyField source ="name" dest ="text" /> <copyField source ="description" dest ="text" /> <dynamicField name ="*_s" type ="string" indexed ="true" stored ="true" />
查询优化建议 1 2 3 4 5 6 7 8 9 10 11 SimpleQuery query = new SimpleQuery (new Criteria ("*:*" ));query.addFilterQuery(new SimpleQuery (new Criteria ("status" ).is("active" ))); CursorMark cursorMark = new CursorMark ("*" );query.setCursorMark(cursorMark); query.setFields("id" , "name" );
监控建议 1 2 3 4 5 6 7 8 9 10 11 curl http://localhost:8983/solr/admin/cores?action=STATUS&wt=json curl http://localhost:8983/solr/admin/metrics?wt=json tail -f server/logs/solr.log
常见问题 中文分词问题 1 2 3 4 5 6 7 问题: 中文无法正确分词 解决方案: 1. 安装 IK 分词器 2. 配置 fieldType 使用 IK 3. 重启 Solr 4. 重新索引数据
内存溢出 1 2 3 4 5 6 7 8 问题: OutOfMemoryError 解决方案: 1. 增加 JVM 堆内存 SOLR_JAVA_MEM="-Xms2g -Xmx4g" 2. 优化查询, 减少返回数据量 3. 调整缓存大小 4. 定期清理旧数据
索引速度慢 1 2 3 4 5 6 7 问题: 批量导入速度慢 解决方案: 1. 使用批量提交 2. 关闭自动提交 3. 并行导入 4. 优化 Schema, 减少不必要的字段
1 2 3 4 5 6 7 8 9 curl -X POST "http://localhost:8983/solr/products/update?commit=false" \ -H 'Content-Type: application/json' \ -d @large_batch.json curl -X POST "http://localhost:8983/solr/products/update?commit=true" \ -H 'Content-Type: application/json' \ -d '{"commit": {}}'
报错处理 💗💗 Solr 报错: Unknown field 1 2 3 4 5 6 7 8 9 10 错误信息: Unknown field 'xxx' 错误原因: 字段未在 schema.xml 中定义 解决方案: 1. 在 schema.xml 中添加字段定义 2. 使用动态字段: xxx_s 3. 重载 Core: curl "http://localhost:8983/solr/admin/cores?action=RELOAD&core=mycore"
💗💗 Solr 报错: Document is missing mandatory uniqueKey field 1 2 3 4 5 6 7 8 9 10 错误信息: Document is missing mandatory uniqueKey field: id 错误原因: 缺少唯一键字段 解决方案: 1. 确保每个文档都有 id 字段 2. 检查 uniqueKey 配置是否正确 3. 使用自动生成 ID
💗💗 Solr 报错: Too many clauses 1 2 3 4 5 6 7 8 9 10 11 错误信息: too many Boolean clauses 错误原因: 查询条件过多 解决方案: 1. 优化查询, 减少条件数量 2. 增加 maxBooleanClauses 限制 <maxBooleanClauses>2048</maxBooleanClauses> 3. 使用 filter 代替 query
学习资源
视频
黑马程序员Solr从基础到实战: https://www.bilibili.com/video/BV1dh411Q7Qu
官方文档
Solr 官方文档: https://solr.apache.org/guide/
Solr GitHub: https://github.com/apache/solr
书籍
《 Solr 实战》 : Erik Hatcher 著
《 Apache Solr Essentials》 : Gaurav Chopra 著
教程
Solr 入门教程: https://www.runoob.com/w3cnote/solr-tutorial.html
Solr 官方示例: https://solr.apache.org/guide/solr/latest/getting-started/solr-tutorial.html
工具
Solr Admin UI: Web 管理界面
Postman: API 测试工具
SolrJ: Java 客户端库
社区
Solr 用户邮件列表: https://solr.apache.org/community.html
Stack Overflow Solr 标签: https://stackoverflow.com/questions/tagged/solr