Combine matches from several fields
The language tabs use earlier client interfaces. Check SDK versions and connection setup before running them.
Search title and description separately, then combine their scores in your application. This example gives title matches more weight.
Before you run it: This native route does not turn several field names into one weighted query. Fetch enough candidates from each field before merging.
The cURL tab shows the four HTTP calls; it does not perform the final merge for you. Use the application-language examples to combine scores by doc_id. With only p001 indexed in both fields, the merge should still produce one item, not two.
- Index title and descriptionUse the same document ID in both fields.
- Search each fieldRun a BM25 request for each indexed field.
- Merge by document IDApply your chosen field weights in the application.
- Show one ranked listAvoid displaying the same document twice.
Follow the example
- Index both fields with the same IDs.
- Run BM25 for each field.
- Merge results by ID.
- Apply the shown weights and sort.
Run the request
Two POSTs to set up (one per field), two GETs to query, one client-side merge step. The doc_id on both fields is the same row PK so the merge can join on it.
# Step 1: index the same row into two separate fields
curl -X POST "https://$OC_HOST/v1/tenants/$OC_TENANT/fts/shop.products/title" \
-H "Authorization: Bearer $OC_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "doc_id": "p001", "text": "Wireless Headphones - Pro" }'
curl -X POST "https://$OC_HOST/v1/tenants/$OC_TENANT/fts/shop.products/description" \
-H "Authorization: Bearer $OC_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "doc_id": "p001", "text": "Over-ear wireless headphones with noise cancellation." }'
# Step 2: query each field, then merge client-side
curl -G "https://$OC_HOST/v1/tenants/$OC_TENANT/fts/shop.products/title" \
-H "Authorization: Bearer $OC_TOKEN" \
--data-urlencode "q=wireless headphones" --data-urlencode "mode=bm25" --data-urlencode "k=20"
curl -G "https://$OC_HOST/v1/tenants/$OC_TENANT/fts/shop.products/description" \
-H "Authorization: Bearer $OC_TOKEN" \
--data-urlencode "q=wireless headphones" --data-urlencode "mode=bm25" --data-urlencode "k=20"Check the result
The application produces the final weighted order.
// merged, sorted client-side
[
{ "doc_id": "p001", "score": 28.92 }, // strong title + description hit
{ "doc_id": "p027", "score": 14.50 }, // description-only hit
{ "doc_id": "p014", "score": 9.10 }
]Understand the behavior
- Each field has its own inverted index and its own document statistics. BM25 on
titleis computed only against other titles - so a match in a 4-word title scores very high. - The two result sets share the
doc_idnamespace because you used the same PK on both POSTs. - You merge by summing weighted scores per
doc_id. Docs that match in both fields naturally float to the top; docs that match in only one are still present but with their single-field score.
Important limits and checks
- Trying to do the merge server-side. There is no multi-field query mode - merging is your app's responsibility. That's deliberate: it keeps the weights tunable without redeploying.
- Concatenating fields into one big text blob. You lose the field-level statistics that make title boost work in the first place. Keep them separate.
- Using too small a
k. If a doc only matches one field, it must be inside that field's top-kto appear in the merge. Pull a largerkper field than you intend to surface. - Using different
doc_ids across fields. The merge joins ondoc_id. Use the row's primary key on every field's POST so that matches from each field refer to the same document.