WEBSITE ĐANG PHÁT TRIỂN

Episerver Find - những điều phải biết trước khi implement

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 đề:

  1. Field weighting không được set đúng: Tôi cân nặng description quá cao so với product name
  2. Analyzer không phù hợp: Nó tìm kiếm từng từ lẻ thay vì câu hoàn chỉnh
  3. 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:

  1. Analyze actual search logs (user search gì, click cái gì?)
  2. Test từng cải tiến trên sample data
  3. Measure impact (CTR, conversion rate on search results)
  4. 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:

  1. Xóa fields không cần
  2. Use term vectors thay vì storing field values
  3. Partition index theo region/locale
  4. 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:

  1. Hiểu Elasticsearch fundamentals
  2. Measure, analyze, iterate trên search relevance
  3. Monitor performance metrics từ ngày đầu
  4. 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:

  1. Chúng tôi có đo CTR trên search results không?
  2. Chúng tôi có setup faceted search cho users filter không?
  3. Chúng tôi có monitor index size và reindex time không?
  4. 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


Bài viết liên quan

Xem thêm
E-commerce & Search Systems

Caching strategy cho product catalog - invalidation mới là bài toán khó

Cache thì dễ thêm vào. Nhưng khi product price thay đổi lúc 11:59 PM trước flash sale lúc 12:00 AM, bạn mới biết cache invalidation khó như thế nào. Bài này đi sâu vào các pattern thực tế và code C# cho product catalog. Phil Karlton có câu nói nổi tiếng: "There are only two hard things in Computer Science: cache invalidation and naming things." Tôi thêm vào: cache invalidation trong e-commerce còn khó hơn cache invalidation ở chỗ khác. Vì trong e-commerce, data thay đổi liên tục - price, stock, promotion - và mỗi inconsistency đều có thể cost bạn money (hoặc cost khách hàng).

E-commerce & Search Systems

Azure Event Hub trong pipeline xử lý đơn hàng real-time

Azure Event Hub không phải message queue - đây là streaming platform. Sự khác biệt này ảnh hưởng đến mọi design decision. Bài này là architecture và code cho order processing pipeline dùng Event Hub - từ kinh nghiệm thực tế.

E-commerce & Search Systems

Search relevance: tại sao người dùng tìm 'áo đỏ' lại ra 'váy xanh

Search relevance không phải là "tìm từ nào match từ đó". Đằng sau một kết quả tìm kiếm là cả một hệ thống scoring phức tạp - và nếu không hiểu nó, bạn sẽ cứ nhận complaint "search dở" mà không biết fix ở đâu.