Solusi Anda benar-benar harus spesifik MongoDB jika tidak, Anda akhirnya akan melakukan perhitungan dan kemungkinan pencocokan di sisi klien, dan itu tidak akan baik untuk kinerja.
Jadi tentu saja yang Anda inginkan adalah cara untuk memprosesnya di sisi server:
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 } }
])
Jadi seperti yang Anda ketahui "panjang" dari $or
kondisi yang diterapkan, maka Anda hanya perlu mencari tahu berapa banyak elemen dalam larik "fitur" yang cocok dengan kondisi tersebut. Jadi itulah $match kedua dalam pipeline.
Setelah Anda menghitungnya, Anda cukup membaginya dengan jumlah kondisi apa yang diteruskan sebagai $or
Anda . Keindahan di sini adalah sekarang Anda dapat melakukan sesuatu yang berguna dengan ini seperti mengurutkan berdasarkan relevansi itu dan bahkan "membuka" sisi server hasil.
Tentu saja jika Anda menginginkan "kategorisasi" tambahan untuk ini, yang perlu Anda lakukan hanyalah menambahkan $project
lainnya tahap ke akhir pipa:
{ "$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"
]}
]}
]}
}}
Atau sebagai sesuatu yang serupa. Tapi $cond
operator dapat membantu Anda di sini.
Arsitekturnya harus baik-baik saja seperti yang Anda miliki karena Anda dapat memiliki indeks gabungan pada "kunci" dan "nilai" untuk entri dalam larik fitur Anda dan ini harus diskalakan dengan baik untuk kueri.
Tentu saja jika Anda benar-benar membutuhkan sesuatu yang lebih dari itu, seperti pencarian segi dan hasil, Anda dapat melihat solusi seperti Solr atau pencarian elastis. Tapi implementasi penuhnya akan agak lama di sini.