Din løsning burde virkelig være MongoDB-specifik, ellers ender du med at lave dine beregninger og mulige matchninger på klientsiden, og det vil ikke være godt for ydeevnen.
Så det, du virkelig ønsker, er selvfølgelig en måde, hvorpå den kan få den behandling på serversiden:
db.products.aggregate([
// Match the documents that meet your conditions
{ "$match": {
"$or": [
{
"features": {
"$elemMatch": {
"key": "Screen Format",
"value": "16:9"
}
}
},
{
"features": {
"$elemMatch": {
"key" : "Weight in kg",
"value" : { "$gt": "5", "$lt": "8" }
}
}
},
]
}},
// Keep the document and a copy of the features array
{ "$project": {
"_id": {
"_id": "$_id",
"product_id": "$product_id",
"ean": "$ean",
"brand": "$brand",
"model": "$model",
"features": "$features"
},
"features": 1
}},
// Unwind the array
{ "$unwind": "$features" },
// Find the actual elements that match the conditions
{ "$match": {
"$or": [
{
"features.key": "Screen Format",
"features.value": "16:9"
},
{
"features.key" : "Weight in kg",
"features.value" : { "$gt": "5", "$lt": "8" }
},
]
}},
// Count those matched elements
{ "$group": {
"_id": "$_id",
"count": { "$sum": 1 }
}},
// Restore the document and divide the mated elements by the
// number of elements in the "or" condition
{ "$project": {
"_id": "$_id._id",
"product_id": "$_id.product_id",
"ean": "$_id.ean",
"brand": "$_id.brand",
"model": "$_id.model",
"features": "$_id.features",
"matched": { "$divide": [ "$count", 2 ] }
}},
// Sort by the matched percentage
{ "$sort": { "matched": -1 } }
])
Så som du kender "længden" af $or
betingelse, der anvendes, så skal du blot finde ud af, hvor mange af elementerne i "features"-arrayet, der matcher disse betingelser. Så det er det, den anden $kamp i pipelinen handler om.
Når du har det antal, dividerer du blot med antallet af betingelser, hvad der blev indført som din $or
. Skønheden her er, at du nu kan gøre noget nyttigt med dette, f.eks. sortere efter den relevans og så endda "side" på resultatserversiden.
Selvfølgelig, hvis du ønsker en ekstra "kategorisering" af dette, skal du blot tilføje endnu et $project
fase til slutningen af pipelinen:
{ "$project": {
"product_id": 1
"ean": 1
"brand": 1
"model": 1,
"features": 1,
"matched": 1,
"category": { "$cond": [
{ "$eq": [ "$matched", 1 ] },
"100",
{ "$cond": [
{ "$gte": [ "$matched", .7 ] },
"70-99",
{ "$cond": [
"$gte": [ "$matched", .4 ] },
"40-69",
"under 40"
]}
]}
]}
}}
Eller som noget lignende. Men $cond
operatør kan hjælpe dig her.
Arkitekturen skulle være fin, som du har den, da du kan have et sammensat indeks på "nøgle" og "værdi" for indtastningerne i dit feature-array, og dette bør skaleres godt for forespørgsler.
Hvis du rent faktisk har brug for noget mere end det, såsom facetteret søgning og resultater, kan du selvfølgelig se på løsninger som Solr eller elastisk søgning. Men den fulde implementering af det ville være lidt langvarig her.