2012-11-21 2 views
0

SQL에 너무 익숙해지면서 mongoDB에이 문제가 발생했습니다. 먼저 몽구스를 사용하고 있습니다.MongoDB 쿼리 결과의 사용자 정의 필드

이제 문제가 발생했습니다. 나는 User이라는 콜렉션을 가지고있다.

var UserSchema = new Schema ({ 
    id : ObjectId, 
    name : {type : String, trim : true, required : true}, 
    email: {type:String, trim:true, required: true, index: { unique: true }}, 
    password: {type:String, required: true, set: passwordToMD5}, 
    age: {type:Number, min: 18, required: true, default: 18}, 
    gender: {type: Number, default:0, required: true}, 

    height: {type: Number, default:180, min: 140, max: 220}, 
    _eye_color: {type: ObjectId, default: null}, 
    location: { 
      lon: {type: Number, default: 0}, 
      lat: {type: Number, default: 0} 
    }, 
    status: {type:Number, required: true, default:0} 
    },{ 
     toObject: { virtuals: true }, 
     toJSON: { virtuals: true }, 
     collection:"user"}); 

이제이 컬렉션의 모든 사용자를 선택하고 특수 속성 (예 : "순위")별로 정렬해야합니다. 이 등급은 주어진 시점과의 거리, 나이와 비교 한 특정 논리에 따라 계산됩니다.

그래서이 순위를 선택한 다음 정렬에 사용하는 방법이 궁금합니다. 가상을 사용하려고 시도했지만 추가 정보를 세는 것이 편리하지만, 불행히도 find() 결과를 가상 필드로 정렬 할 수는 없습니다. 물론 가상에서이 순위를 계산 한 다음 모든 레코드를 선택한 다음 콜백에서 일부 자바 스크립트를 수행 할 수 있습니다. 하지만이 경우 모든 사용자를 선택하고 정렬 한 다음 자바 스크립트 부분이 너무 오래 걸릴 수 있습니다. mapreduce을 사용하려고 생각했지만 그게 내가 원하는 것을 할 수 있을지 확신 할 수 없습니다. 내 작업이 가능할 경우 누군가 내게 힌트를 줄 수 있습니까 mongoDB/mongoose? 1

편집은 또한 통합 프레임 워크를 사용하는 것을 시도했다, 처음에는 $project 능력을 가진 최고의 솔루션이 될 것 같았다. 그러나 순위 계산이 필요할 때, 나는 집계가 sin, cossqrt과 같은 많은 수학 함수를 지원하지 않는다는 것을 알았습니다. 또한 사전 정의 된 일반적인 자바 스크립트 함수를 프로젝션에 사용하는 것은 불가능했습니다. 함수가 호출되었지만 현재 레코드 필드를 전달할 수 없었습니다.

{$project: { 
    distance_from_user: mUtils.getDistance(point, this.location) 
} 

내부 기능은 두 번째 attr이 "정의되지 않음"입니다.

그래서 집계 프레임 워크로 내 순위 계산을 수행하는 것은 불가능합니다. 2 확인

편집, 나는 모든 사람들이 실시간 쿼리 좋지 않다으로 맵리 듀스를 사용하지 말라고 말한다 알고,하지만 난 집계를 사용할 수 없기 때문에, 나는 맵리 듀스를 시도 할 것 같아요. 자,이지도를 축소한다고 가정 해 봅시다.

function map() { 
      emit(1, // Or put a GROUP BY key here 
       {name: this.name, // the field you want stats for 
        age: this.age, 
        lat: this.location.lat, 
        lon: this.location.lon, 
        distance:0, 
        rank:0 

       }); 
     } 

     function reduce(key, values) { 


      return val; 
     } 

     function finalize(key, value){ 

      return value; 
     } 


     var command = {'mapreduce': "user", 'map': map.toString(), 'reduce': reduce.toString(), query:{$and: [{gender: user_params.gender}, {_id: {$ne: current_user_id}}]}, 'out': {inline:1}}; 

     mongoose.connection.db.executeDbCommand(command, function(error, result){ 
      if(error) { 
       log(error); 
       return; 
      } 
      log(result); 
      return; 
     }); 

모든 사용자의 순위를 계산하려면 무엇을 줄이거 나 변경해야합니까?

+1

'실시간'쿼리에 mapreduce를 사용하지 마십시오. 집계 프레임 워크 살펴보기 http://docs.mongodb.org/manual/applications/aggregation/ – Alex

+0

집계를 시도했지만 집계 프레임 워크에서 순위 계산에 필요한 함수를 사용할 수 없습니다. 예를 들어'sqrt()','sin()','cos()'등은 없습니다. – ArVan

답변

1

유일한 해결책은 각 문서의 순위를 계산하여 문서에 저장하는 것입니다. 이 값은 문서의 값이 일정한 한 일정 할 것이므로 영향을주는 필드를 업데이트 할 때마다이 값을 계산하면됩니다.

Map/reduce는 확실히이 솔루션이나 다른 유형의 집계가 아닙니다. MongoDB를 사용하는 경우 순위를 미리 계산하고 문서와 함께 저장하는 것이 유일한 옵션입니다.

+0

로그인 한 사용자의 세부 사항에 대한 계산이 수행되기 때문에 결과를 계산하고 저장할 수 없습니다. 따라서이 순위는 시스템의 모든 사용자마다 다릅니다. – ArVan

+0

그래서 가상을 시도했습니다. – ArVan

+0

다른 대안으로 순위를 생성하기 위해 주기적으로 실행되는 mapreduce가 있다고 생각하십니까? – Alex

0

MongoDB + Hadoop의 좋은 사용 예입니다.

presentation은이 조합의 가능성 중 일부를 보여줍니다.

+0

흠 ... ** node.js와 함께 사용하는 것이 불가능하다고 생각합니다 ** ** – ArVan

+0

[일괄 집계] (http://www.mongodb.org/display/DOCS/Hadoop+Scenarios) 시나리오에서 node.js는 hadoop과 상호 작용할 필요가 없습니다. Java에서 mapreduce를 작성해야합니다. 일부 [예제] (https://github.com/mongodb/mongo-hadoop/tree/master/examples)는 github에 있습니다. – Eric

1

당신은 사용자가 로그인 할 때마다 그렇게한다면, 많은 사람들이 더 짧은 시간에 로그인 할 때 흥미로운로드 피크를 갖게 될 것입니다. 페이지 (인터페이스)가 자원에 중대한 영향을 미친다.
나는 조금 다른 것을 권하고 싶습니다 - 로그온 한 모든 사용자의 순위를 매기고 간격으로 업데이트하는 것이 좋습니다 : "짧은 세션"과 "긴 세션"(긴 세션 - 웹 브라우저에서 사용하는 짧은 세션) "온라인, 현재 사이트 사용") 및 "단기간 활성"사용자에 대해서만 정기적으로 순위를 생성하고 긴 세션에서 거의 로그온하지 않습니다. 5 분마다와 같은 것. 훨씬 더 scallable - 그리고 사용자가 자신의 계급을 계산하지 않는 것에 대해 불만이 있다면 - 당신은 항상 요구에 따라 자신의 순위를 계산하기 위해 시스템을 조정할 수 있습니다.
그런 경우 mapaddurce를 사용할 수 있습니다.지도 기능은 테스트 한 사용자에 대해 주어진 사용자 (예 : 연령, 위도, 경도, 필요에 따라) 및 순위 (계급)에 대한 순위를 계산하는 데 필요한 데이터 만 내야합니다 (비워 둬라). reduce 함수의 경우 mapreduce (순위를 만드는 방식에 따라 크게 다름)로 정렬해야합니다. 다른 사용자의 순위 (또는 하위 값)를 계산할 수도 있습니다.

+2

이 솔루션을 사용하면 온 디맨드 계산보다 리소스 소비가 상당히 높습니다. 순위에 영향을주는 값을 변경하지 않고 동일한 사용자에 대한 순위를 다시 계산할 가능성이 큽니다. 또한로드 피크는 기능적으로 순위 계산을 비동기식으로 수행 할 수있는 경우 문제가되지 않습니다 (단순히 리콜 대기열에 놓고 원하는 성능 패턴 인 피크가있는 경우 길게 걸릴 것입니다). –

+0

모두 다 다릅니다. 페이지가 자주 사용되고 계산에 리소스가 많은 경우 일정 기간의 계산량을 제어 가능한 상태로 유지하는 것이 훨씬 좋습니다. 일종의 캐싱 또는 사용과 함께 요청시 생성 될 수 있습니다 기본적으로 요구에 따라 수행되지 않는 시간 기반 계산과 같은 것입니다. 요청에 따라 모든 것을 수행하는 것을 막을 것입니다. 완전히 이해할 수 없기 때문입니다. –

+1

주기적 작업 부하와 마찬가지로 주문형 비동기 작업 부하 대기열에 동일한 제한 규칙을 적용 할 수 있습니다. 로드 예측 가능성은 분명 중요한 요소이지만로드 피크에 대해 언급하는 경우 예측 가능성이 이미 제한되어 있다고 가정합니다. 온 디맨드 (on-demand)는 예를 들어 최대 로그인을 처리해야하는 거의 모든 시스템이 자동 균형을 유지하기 때문에 (로그인/느린 로그인 대기열 -> 온 디맨드 계산이 적음) 쉽게 조절할 수 있기 때문에 (예 : 로그인 대기열, 거기 밖으로 거의 모든 큰 도박 서비스를보십시오). –