Cái tối mặt lần đầu tiên
Năm 2015, tôi nhận được task triển khai search cho một platform e-commerce lớn - hệ thống có gần 500K SKU và 2 triệu customer. Lúc đó team chọn Episerver Find vì nó là "chuẩn" cho việc tích hợp với Episerver Commerce. Đơn giản mà, tôi nghĩ.
Sai bét.
Ba tuần sau, khách hàng gọi: "Mình tìm 'áo khoác' nhưng hiển thị cái quần dài đứng hàng đầu. Sao vậy?"
Search result đầu tiên là quần dài. Lý do? Nó có từ "khoác" trong description, Elasticsearch score cao hơn, nhưng relevance hoàn toàn sai. Lúc đó mình mới bắt đầu hiểu: Episerver Find không phải "cắm cắp" và "xài được". Nó là một công cụ mạnh mẽ nhưng đòi hỏi bạn hiểu rõ triết lý của nó.
Hôm nay tôi muốn chia sẻ 7 điều mà tôi học được (cách đau đớn) khi làm việc với Episerver Find. Những kinh nghiệm này giúp bạn tránh mắc phải các lỗi mà team tôi đã gặp.
1. Episerver Find không phải Elasticsearch - nhưng nó dùng Elasticsearch
Đây là điểm gây nhầm lẫn lớn nhất.
Episerver Find là wrapper của Elasticsearch. Nó cung cấp .NET API rất tiện lợi, support tích hợp với Episerver Commerce, và auto-indexing khi content publish. Nhưng under the hood, nó vẫn là Elasticsearch.
Điều này có nghĩa gì?
Nếu bạn chỉ dùng Episerver Find API mà không hiểu Elasticsearch fundamentals, bạn sẽ bị giới hạn. Ví dụ, khi cần fine-tune relevance scoring, bạn cần biết cách sử dụng boost factors, field weights, và custom analyzers.
// API Episerver Find - đơn giản và tiện
var results = client.Search<Product>()
.Filter(x => x.Status.Match("Active"))
.Query(q => q.For(searchText))
.ApplyBestBets()
.Select(x => new { x.Name, x.Price })
.GetResult();
// Nhưng nếu cần relevance tuning, bạn phải "drop down"
// vào Elasticsearch query DSL:
// Boost field, fuzzy matching, synonym handling...
// Và lúc đó, bạn cần hiểu Elasticsearch, không chỉ Episerver API
Bài học: Hãy dành thời gian học Elasticsearch basics - scoring, analyzers, query types. Nó sẽ giúp bạn debug search problems hiệu quả hơn nhiều.
2. Relevance tuning là một nghệ thuật, không phải khoa học
Quay lại câu chuyện "áo khoác vs quần dài" ở trên. Tôi đã tìm ra vấn đề:
- Field weighting không được set đúng: Tôi cân nặng description quá cao so với product name
- Analyzer không phù hợp: Nó tìm kiếm từng từ lẻ thay vì câu hoàn chỉnh
- Synonym mapping bị thiếu: Không có rule để match "áo khoác" với "jacket"
Episerver Find cung cấp công cụ để xử lý các vấn đề này:
- Content Boosting: Tăng priority cho sản phẩm bestseller hoặc new arrival
- Synonym Management: Setup rule để "sneaker" = "giày thể thao"
- Boost Factors: Tăng score nếu match ở field Name (nguyên nhân chính tôi cần boost)
- Faceted Search: Để user có thể lọc theo category, price range, rồi sort
// Ví dụ: boost product name field, add synonyms
var results = client.Search<Product>()
.Query(q => q.For(searchText))
.Facets(x => x.Category) // Faceted search
.Facets(x => x.PriceRange)
.OrderBy(x => x.Score.Descending()) // Relevance first
.GetResult();
Nhưng đây là phần khó: không có công thức ma thuật. Bạn phải:
- Analyze actual search logs (user search gì, click cái gì?)
- Test từng cải tiến trên sample data
- Measure impact (CTR, conversion rate on search results)
- Iterate
Hầu hết team tôi làm việc với bắt đầu bằng cách đoán (worst case) hoặc copy từ tutorial (second worst case). Đúng way là instrument, measure, iterate.
3. GetContentResult vs GetResult - hiệu năng không phải tự nhiên
Đây là một sai lầm kinh điển mà tôi thấy trong code review suốt ngày.
Episerver Find cung cấp hai method chính:
// GetResult() - trả về từng search result là một object
var results = client.Search<Product>()
.GetResult(); // Nhanh, nhưng chỉ lấy data đã index
// GetContentResult() - load full content từ database
var results = client.Search<Product>()
.GetContentResult(); // Chậm, nhưng data hoàn toàn mới nhất
Sự khác biệt:
GetResult(): Dữ liệu từ Elasticsearch index. Nhanh, nhưng có độ trễ (reindex delay)GetContentResult(): Load từ database. Luôn mới nhất, nhưng chậm vì gọi DB cho từng result
Năm 2015, mình đã sử dụng GetContentResult() cho tất cả search queries. Kết quả? Page load time từ 200ms lên 1.5s. Vì sao?
Vì Episerver Find index ~30 fields, nhưng page chỉ cần 5: name, price, image, category, rating. Tôi lấy dữ liệu dư thừa 6x.
Bài học: Hãy index các field bạn cần hiển thị + filter. Dùng GetResult() cho listing pages (vì user scroll qua nhanh), nhưng GetContentResult() cho detail pages (vì cần data hoàn toàn mới nhất).
4. Faceted search - không phải optional, là essential cho e-commerce
Trong e-commerce, user không chỉ search - họ filter.
Episerver Find support faceted search bằng TermsFacetFor(), RangeFacetFor(), và hierarchical facets. Nhưng nhiều team bỏ qua feature này - và đó là sai lầm.
Vì sao? Vì faceted search giảm search result từ 10,000 xuống 50 - điều này tăng conversion rate đáng kể.
// Faceted search example
var results = client.Search<Product>()
.Query(q => q.For("shirt"))
.Facets(x => x.Category) // Terms facet
.Facets(x => x.PriceRange) // Range facet
.Filter(x => x.Category.Match("Men's")) // User filter
.Filter(x => x.Price.Range(50, 200))
.GetResult();
// results.Facets sẽ chứa:
// - Category: { "T-Shirt" (45), "Polo" (32), "Dress Shirt" (18) }
// - Price: { "0-50" (12), "50-100" (55), "100-200" (28), "200+" (5) }
Team e-commerce nên auto-generate facets từ product metadata, không hard-code. Dùng dynamic facet configuration để editor có thể reorder hoặc hide facets mà không cần code.
5. Index size sẽ trở thành bottleneck của bạn
Episerver Find index mọi version của content. Nếu bạn có 500K product × 20 edits per year, đó là 10M documents.
Cộng thêm:
- Multiple languages (index riêng per language)
- Synonym lists lớn
- Boost rules
- Custom fields
Index size có thể vọt tới hàng GB. Nếu bạn không management nó:
- Reindex time từ 30 phút lên 3 giờ
- Disk space vượt budget
- Search latency tăng
Bài học: Setup monitoring cho index size, reindex time, query latency từ ngày đầu. Nếu index quá lớn:
- Xóa fields không cần
- Use term vectors thay vì storing field values
- Partition index theo region/locale
- Archive old data
6. Episerver Find không phải cho tất cả loại search
Đây là lesson quan trọng mà tôi học quá muộn.
Episerver Find xuất sắc cho:
- Full-text search (product name, description)
- Faceted search (category, price range)
- Real-time indexing (content publish → search available immediately)
- E-commerce product discovery
Nhưng nó không tốt cho:
- Autocomplete / Typeahead: Elasticsearch có, nhưng Episerver Find API chưa optimize. Dùng specialized service (Azure Search, Algolia)
- Fuzzy matching trên large datasets: Chậm, cần custom query tuning
- Geo-spatial search: Có, nhưng không tốt bằng Elasticsearch native
- Complex aggregations: Nếu cần statistics, pivot tables, dùng DB hoặc Elasticsearch direct
Một lần, client yêu cầu "show products ordered by distance from user location". Tôi sử dụng Episerver Find geo-spatial facets - query timeout vì dataset lớn. Lúc đó, tôi mới hiểu: Episerver Find là wrapper tốt, nhưng nó không thay thế Elasticsearch cho các use case phức tạp.
7. Debugging search problems - phương pháp hiệu quả
Cuối cùng, cách để debug search issue.
Episerver Find API không expose underlying Elasticsearch query. Nhưng bạn có thể:
// 1. Inspect lên Elasticsearch trực tiếp
// Kết nối vào Elasticsearch endpoint và chạy query
// Mình hay dùng Postman hoặc curl:
curl -X GET "localhost:9200/episerver-find-index/_search?q=shirt"
// 2. Enable debug logging
// Các Episerver Find logs sẽ cho thấy execution time, hit count, etc.
// 3. Use Elasticsearch Dev Tools
// Inspect query structure, timing, scoring
// 4. A/B test search improvements
// Thay đổi boost factors, reindex, measure CTR
Best practice: setup structured logging (Application Insights, ELK stack) để track search metrics:
- Query latency (p50, p95, p99)
- Hit rate (queries returning 0 results)
- User behavior (click-through rate on rank 1 vs rank 10)
- Index reindex time
Triết lý: "Believe in basic"
Sau 20 năm làm việc với các hệ thống search, tôi học được điều này: không có shortcut.
Episerver Find là công cụ tuyệt vời, nhưng nó không thay thế cho việc:
- Hiểu Elasticsearch fundamentals
- Measure, analyze, iterate trên search relevance
- Monitor performance metrics từ ngày đầu
- Biết boundary của tool (khi nào dùng, khi nào không)
Nhiều team muốn "implement và forget". Không được. Search engine là sống - bạn phải feeding và nurturing nó.
Hãy bắt đầu đơn giản: index core fields, setup basic facets, measure user behavior. Rồi iterate từ đó. Mỗi 1% improvement trên search relevance = 1% improvement trên conversion rate. Nó là một trong những ROI cao nhất mà bạn có thể làm.
Câu hỏi để bạn
Nếu bạn đang implement Episerver Find, hãy tự hỏi:
- Chúng tôi có đo CTR trên search results không?
- Chúng tôi có setup faceted search cho users filter không?
- Chúng tôi có monitor index size và reindex time không?
- Chúng tôi biết Elasticsearch query language không?
Nếu trả lời "không" cho bất cứ câu nào, đó là cơ hội để improve.
Hãy để tôi biết kinh nghiệm của các bạn - mình rất muốn nghe những lessons khác mà các bạn đã học được khi implement search.
/Son Do - believe in basic
#1percentbetter #episerverfind #ecommerce #dotnet #searchsystems #elasticsearch