2016-08-25 57 views
2

mongoose(和/或mongodb)中是否有函數/方法可用於基於相關性對查詢結果進行排序(匹配查詢參數的最大數量)?按相關性排序的性能問題

下面的示例是我目前使用的(查詢使用$in:[],否則相同) - 我的集合非常小,因此性能很好,但對於較大的集合,它會顯着減慢速度。

或者,如果有更好的執行方法(貓鼬/ mongodb之外),我很樂意瞭解它。

例子:

var docs = [ 
    { 
     fruits: ['apple', 'orange', 'tomato'], 
     colors: ['blue', 'green'], 
     // relevance: 3 
    }, 
    { 
     fruits: ['apple', 'carrot'], 
     colors: ['red', 'green'], 
     // relevance: 2 
    } 
] 

var query = {fruits: ['apple', 'orange'], colors: ['green']} 

docs.forEach(function(doc){ 
    var relevance = 0 
    Object.keys(query).forEach(function(_query){ 
     var arrays = [doc[_query], query[_query]] 
     var result = arrays.shift().filter(function(v) { 
      return arrays.every(function(a) { 
       return a.indexOf(v) !== -1; 
      }); 
     }); 
     relevance += result.length 
    }) 
    doc.relevance = relevance 
}) 

結果:

var docs = [ 
    { 
     fruits: ['apple', 'orange', 'tomato'], 
     colors: ['blue', 'green'], 
     relevance: 3 
    }, 
    { 
     fruits: ['apple', 'carrot'], 
     colors: ['red', 'green'], 
     relevance: 2 
    } 
] 
+0

你能還添加預期的輸出? – Shrabanee

+0

在總是包含兩個項目的數組上使用'array.shift()'和'arrays.every'幾乎沒有意義。 – Bergi

+0

@Bergi在查詢中可以使用十幾個數組,可以使用'.shift()'和'.every()'來覆蓋動態構建的查詢。 – brod

回答

0

你可以用聚集做到這一點:

db.getCollection('docs').aggregate([ 
 
{$match: {fruits: {$in: ['apple', 'orange']}, colors: {$in: ['green']}}}, 
 
{$project: { 
 
    relevance: { 
 
     $sum: [ 
 
      {$cond: {if: { "$setIsSubset": [['orange'], "$fruits" ]}, then: 1, else: 0}}, 
 
      {$cond: {if: { "$setIsSubset": [['apple'], "$fruits" ]}, then: 1, else: 0}}, 
 
      {$cond: {if: { "$setIsSubset": [['green'], "$colors" ]}, then: 1, else: 0}}] 
 
    }, 
 
    doc: '$$ROOT'}} 
 
])

結果:

/* 1 */ 
 
{ 
 
    "_id" : ObjectId("57be8a9b65d2835e960df543"), 
 
    "relevance" : 3, 
 
    "doc" : { 
 
     "_id" : ObjectId("57be8a9b65d2835e960df543"), 
 
     "fruits" : [ 
 
      "apple", 
 
      "orange", 
 
      "tomato" 
 
     ], 
 
     "colors" : [ 
 
      "blue", 
 
      "green" 
 
     ] 
 
    } 
 
} 
 

 
/* 2 */ 
 
{ 
 
    "_id" : ObjectId("57be8aa865d2835e960df544"), 
 
    "relevance" : 2, 
 
    "doc" : { 
 
     "_id" : ObjectId("57be8aa865d2835e960df544"), 
 
     "fruits" : [ 
 
      "apple", 
 
      "carrot" 
 
     ], 
 
     "colors" : [ 
 
      "red", 
 
      "green" 
 
     ] 
 
    } 
 
}