在Go中集成Solr进行数据索引,可以使用github.com/vanng822/go-solr/solr包。以下是一个完整的示例,展示如何连接Solr并索引文档:
package main
import (
"fmt"
"log"
"github.com/vanng822/go-solr/solr"
)
func main() {
// 创建Solr连接
si, err := solr.NewSolrInterface("http://localhost:8983/solr", "mycore")
if err != nil {
log.Fatal(err)
}
// 准备要索引的文档数据
docs := []solr.Document{
{
"id": "1",
"title": "Go语言编程",
"author": "张三",
"content": "Go语言并发编程实战",
"publish_date": "2023-10-01T10:30:00Z",
},
{
"id": "2",
"title": "Solr搜索引擎",
"author": "李四",
"content": "Solr分布式搜索架构",
"publish_date": "2023-10-02T14:45:00Z",
},
}
// 创建索引请求
params := &solr.DocumentAddParams{
Commit: true, // 提交更改
Overwrite: true, // 覆盖已存在文档
}
// 执行索引操作
resp, err := si.Add(docs, 0, params)
if err != nil {
log.Fatal("索引失败:", err)
}
if resp.Success {
fmt.Printf("成功索引 %d 个文档\n", len(docs))
fmt.Printf("响应状态: %d\n", resp.Status)
} else {
fmt.Printf("索引失败: %v\n", resp.Error)
}
// 查询验证
query := solr.NewQuery()
query.Q("*:*")
query.Rows(10)
s := si.Search(query)
r, err := s.Result(nil)
if err != nil {
log.Fatal("查询失败:", err)
}
fmt.Printf("总文档数: %d\n", r.Results.NumFound)
for _, doc := range r.Results.Docs {
fmt.Printf("文档ID: %v, 标题: %v\n", doc["id"], doc["title"])
}
}
对于批量索引大量数据,可以使用以下优化方案:
func batchIndex(si *solr.SolrInterface, documents []solr.Document, batchSize int) error {
for i := 0; i < len(documents); i += batchSize {
end := i + batchSize
if end > len(documents) {
end = len(documents)
}
batch := documents[i:end]
params := &solr.DocumentAddParams{
Commit: false,
Overwrite: true,
}
resp, err := si.Add(batch, 0, params)
if err != nil {
return fmt.Errorf("批次 %d 索引失败: %v", i/batchSize, err)
}
if !resp.Success {
return fmt.Errorf("批次 %d 响应错误: %v", i/batchSize, resp.Error)
}
fmt.Printf("已处理批次 %d: %d 个文档\n", i/batchSize, len(batch))
}
// 最后提交所有更改
_, err := si.Commit()
return err
}
处理复杂字段类型的示例:
func indexWithComplexFields() {
si, _ := solr.NewSolrInterface("http://localhost:8983/solr", "products")
docs := []solr.Document{
{
"id": "prod_001",
"name": "笔记本电脑",
"price": 5999.99,
"stock": 50,
"features": []string{"16GB内存", "512GB SSD", "独立显卡"},
"specs": map[string]interface{}{
"cpu": "Intel i7",
"ram": "16GB",
"storage": "512GB",
},
"categories": []string{"电子产品", "电脑", "办公设备"},
"tags": []string{"高性能", "便携", "商务"},
"timestamp": "2023-10-05T09:15:30Z",
},
}
params := &solr.DocumentAddParams{
Commit: true,
Overwrite: true,
}
resp, err := si.Add(docs, 0, params)
if err != nil {
log.Fatal(err)
}
fmt.Printf("索引响应: %+v\n", resp)
}
错误处理和连接配置:
type SolrClient struct {
si *solr.SolrInterface
}
func NewSolrClient(host, core string, timeout int) (*SolrClient, error) {
si, err := solr.NewSolrInterface(host, core)
if err != nil {
return nil, fmt.Errorf("创建Solr连接失败: %v", err)
}
// 可以设置HTTP客户端配置
// si.SetHTTPClient(&http.Client{Timeout: time.Duration(timeout) * time.Second})
return &SolrClient{si: si}, nil
}
func (sc *SolrClient) IndexDocument(doc solr.Document) error {
params := &solr.DocumentAddParams{
Commit: true,
Overwrite: true,
}
resp, err := sc.si.Add([]solr.Document{doc}, 0, params)
if err != nil {
return fmt.Errorf("索引文档失败: %v", err)
}
if !resp.Success {
return fmt.Errorf("Solr响应错误: %v", resp.Error)
}
return nil
}
func (sc *SolrClient) DeleteDocument(id string) error {
resp, err := sc.si.Delete(id, nil)
if err != nil {
return fmt.Errorf("删除文档失败: %v", err)
}
if !resp.Success {
return fmt.Errorf("Solr删除响应错误: %v", resp.Error)
}
_, err = sc.si.Commit()
return err
}
这些示例展示了使用go-solr包进行基本索引操作、批量处理、复杂字段索引和错误处理的方法。确保Solr服务运行在指定地址,且core名称正确。