2013-04-07 2 views
2

DB에서 가장 일치하는 문서를 반환하는 쿼리를 작성하고 싶습니다.Mongodb가 가장 일치하는 항목을 찾습니다.

즉, 나는 다음과 같은 필드 문서를 찾을 싶습니다 - "동물": "개" "색상": "갈색" "패턴": "점" "크기": "작은"

위의 모든 내용과 해당 값이있는 문서가없는 경우 쿼리에서 가장 일치하는 항목을 반환하고 싶습니다. foo { "animal": "dog", "color": "brown", "size": "small"}

mongo db에서 재귀 쿼리를 구현할 수 있습니까? 그렇다면 어떻게? mapReduce를 사용해야합니까? 그렇다면 어떻게해야합니까? 주어진 값에 가장 잘 맞는 항목 (문서)을 추천하고 싶다면이 문제를 추천 시스템 문제로 더 생각할 수 있습니다. 누군가가 위의 구현 방법을 잘 알고 있다면 감사하겠습니다.

나는 mongodb mongoose와 nodejs를 사용하고 있습니다.

감사합니다.

+1

집계 프레임 워크를 사용하여 필드를 일치시키고 일치 항목의 개수 (점수)를 유지 한 다음 정렬 할 수 있습니다 (http://docs.mongodb.org)./manual/tutorial/aggregation-examples /). (그리고, 당신은 기본적으로 '재귀 적 쿼리'를 할 수 없습니다.) – WiredPrairie

답변

1

재귀 쿼리가 성능에 미치는 영향에 대해서는 확신 할 수 없지만 이와 같은 것이 작동해야합니다. 그것은 쿼리에서 마지막 속성을 제거하고 일치하는 항목이없는 경우 다시 시도합니다

var AnimalSchema = new mongoose.Schema({ 
    atype: { type: String }, 
    color: {type:String}, 
    pattern: {type:String}, 
    size : {type:String} 
}); 

var Animal = mongoose.model('Animal',AnimalSchema); 

//test data 
//var dalmation = new Animal({ 
// atype:'dog', 
// color: 'black and white', 
// pattern: 'spots', 
// size: 'big' 
//}); 

//dalmation.save(function(err){ 
// var yorkie = new Animal({ 
//  atype:'dog', 
//  color:'brown', 
//  pattern:'mixed', 
//  size:'small' 
// }); 
// yorkie.save(function(yer){ 
//   bestMatch({'atype':'dog','size':'big','color':'brown'},function(err,animal){ 
//    console.log(err,animal); 
//   }) 
// }); 
//}); 

function bestMatch(params,cb){ 
    Animal.findOne(params,function(err,animal){ 
     if (err || !animal){ 
      var keys = Object.keys(params); 
      if (keys.length){ 
       delete params[keys.pop()]; 
       bestMatch(params,cb); 
      }else{ 
       cb('No matches',null); 
      } 
     }else{ 
      cb(null,animal); 
     } 
    }); 
} 

bestMatch({'atype':'dog','size':'big','color':'brown'},function(err,animal){ 
    console.log(err,animal); 
}); 
+0

나는 집계 프레임 워크를 사용하여 대답을보기를 희망했다. 하나를 보는 것이 좋을 것입니다! – Manu

0

당신은 텍스트 필드를 검색하는 것으로 나타 점을 감안, 하나의 가능성은 새로운 (현재 "실험") text search feature를 사용하는 것입니다 MongoDB에서 2.4. 이렇게하면 하나 이상의 필드에 전체 텍스트 인덱스를 만들 수 있습니다. 관련성을 위해 field weighting을 포함합니다. 예를 들어

:

db.collection.ensureIndex(
    // Fields to index 
    { 
     animal: "text", 
     color: "text", 
     pattern: "text", 
     size: "text" 
    }, 

    // Options 
    { 
     name: "best_match_index", 

     // Adjust field weights (default is 1) 
     weights: { 
      animal: 5, // Most relevant search field 
      size: 4 // Also relevant 
     } 
    } 
) 

Results은 관련 분야의 가중치에 따라 점수와의 관련성의 순서로 반환됩니다.

검색 키워드는 stemmed이기 때문에 정확한 일치가 예상되는 경우 예기치 않은 결과가 발생할 수 있습니다. 보다 구체적인 성냥을 위해 phrase matching을 이용하기 위해 조건을 큰 따옴표로 묶을 수 있습니다.

+0

당신이 제안한 것을 시도했지만 "너무 많은 인덱스"오류가 발생했습니다 – Liatz

+0

@Liatz : 얼마나 많은 인덱스가 있습니까 ('db.collection.getIndexes(). length')? 이 오류는 컬렉션에 너무 많은 인덱스가 있거나 여러 텍스트 인덱스를 만들려고했습니다 (2.4 컬렉션 당 하나의 텍스트 인덱스 만 허용 함). – Stennie

+0

다중 색인을 지원하는 버전은 무엇입니까? (나는 같은 컬렉션에서 4-5 개의 인덱스와 와이트를 사용해야한다.) – Liatz