Multi-Listing Combinations
When no single listing can accommodate all guests, the system groups nearby listings together.
When Combinations Trigger
if (allowCombination == true AND singleFitCount < minSingleResults):
build combinations
minSingleResultsdefaults to 3 — combinations only activate if fewer than 3 listings can fit everyone alone
How It Works
- Candidates: All processed listings with
maxAdults > 0, capped at 30 - Generate groups: Sizes 2 to
maxListingsInGroup(default 3) - Capacity check: Combined
totalAdults >= required AND totalChildren >= required - Proximity filter (optional):
- If
anchorLat/anchorLonset: all listings must be withinproximityMetersof anchor - If no anchor: all pairwise distances must be within
proximityMeters
- If
- Score each group:
score = discountWeight (capped at 40)
+ 30 × (1 - min(maxPairwiseDistance / 1000, 1))
+ 20 / listingCount
- Higher discount % → higher score
- Closer together → higher score
- Fewer listings in group → higher score (prefer 2 over 3)
- Sort by score (best first)
Group ID
Combined groups get a composite ID:
lst_abc+lst_def+lst_ghi
This ID is used for the detail API to fetch the combined breakup.
Proximity Labels
| Distance | Label |
|---|---|
| < 500m | "Within 500m" |
| 500m - 1km | "500m - 1km" |
| 1km - 2km | "1-2km" |
| 2km - 5km | "2-5km" |
| > 5km | "5km+" |
Response
{
"combinedGroups": [
{
"groupId": "lst_abc+lst_def",
"listings": [ ... full listing cards ... ],
"totalAdultCapacity": 12,
"totalChildrenCapacity": 6,
"maxPairwiseDistanceMeters": 350.0,
"proximityLabel": "Within 500m",
"price": {
"total": 45000,
"perNight": 22500,
"totalBeforeDiscount": 52000,
"totalSaving": 7000,
"discountPercent": 13
}
}
]
}