2014-06-13 20 views
2

之後填充子文檔我正在使用NodeJs和Mongoose,並構建一項功能以便按交易列出。

Deal.db.db.command({ 
    "geoNear": Deal.collection.name, 
    "near": [23,67], 
    "spherical": true, 
    "distanceField": "dis" 
    }, function (err, documents) { 
    if (err) { 
     return next(err); 
    } 
    console.log(documents); 
    }); 

交易模式:

var dealSchema = new mongoose.Schema({ 
    title: String, 
    merchant: { 
    type: mongoose.Schema.Types.ObjectId, 
    ref: Merchant, 
    index: true 
    } 
}); 

在這裏,我得到的所有交易,並從當前位置它們的距離。 Inside Deal模式我有一個商家作爲參考對象。

如何使用每個返回的Deal對象填充商家? 我是否需要迭代所有返回的交易對象並手動填充?

+1

在這裏注意到你已經挖掘到'db'對象並從本機驅動程序執行一個方法。所以這不再是貓鼬文件(或文件)。 –

+0

我會使用Mongoose並運行'find({near})',但是,它不會按照離我們最近的順序排序。如果我能做到這一點,我會用'填充'。任何其他的指針/想法都會有所幫助。謝謝。 – ankitjaininfo

回答

3

這實際上很有趣。當然,你不想真正做的是「潛入」本地驅動程序的一部分,儘管你可能會在解決方案2上。這導致有幾種方法可以解決這個問題,而不需要真正滾動自己的查詢來手動匹配。

首先稍微設置一下。我沒有重現你的數據集,而是選擇了我之前測試過的東西。這些原則是一樣的,所以一個基本設置:

var mongoose = require('mongoose'), 
    async = require('async'), 
    Schema = mongoose.Schema; 

mongoose.connect('mongodb://localhost'); 

var infoSchema = new Schema({ 
    "description": String 
}); 

var shapeSchema = new Schema({ 
    "_id": String, 
    "amenity": String, 
    "shape": { 
    "type": { "type": String }, 
    "coordinates": [] 
    }, 
    "info": { "type": Schema.Types.ObjectId, "ref": "Info" } 
}); 

var Shape = mongoose.model("Shape", shapeSchema); 
var Info = mongoose.model("Info", infoSchema); 

基本上一個模型,是與剛剛我們要填充一些信息參考的「地理」信息和其他。此外,我懶惰的數據更改:

{ 
    "_id" : "P1", 
    "amenity" : "restaurant", 
    "shape" : { "type" : "Point", "coordinates" : [ 2, 2 ] } 
} 
{ 
    "_id" : "P3", 
    "amenity" : "police", 
    "shape" : { "type" : "Point", "coordinates" : [ 4, 2 ] } 
} 
{ 
    "_id" : "P4", 
    "amenity" : "police", 
    "shape" : { "type" : "Point", "coordinates" : [ 4, 4 ] } 
} 
{ 
    "_id" : "P2", 
    "amenity" : "restaurant", 
    "shape" : { "type" : "Point", "coordinates" : [ 2, 4 ] }, 
    "info" : ObjectId("539b90543249ff8d18e863fb") 
} 

所以有一件事,我們可以期待填充。事實證明一個$near查詢很簡單,因爲它的排序預期:

var query = Shape.find(
    { 
    "shape": { 
     "$near": { 
     "$geometry": { 
      "type": "Point", 
      "coordinates": [ 2, 4 ] 
     } 
     } 
    } 
    } 
); 

query.populate("info").exec(function(err,shapes) { 
    if (err) throw err; 
    console.log(shapes); 
}); 

這僅僅是一個標準的.find()與調用$near運營商。這是MongoDB 2.6語法,所以就是這樣。但結果排序正確,並按預期填充:

[ 
    { _id: 'P2', 
     amenity: 'restaurant', 
     info: 
     { _id: 539b90543249ff8d18e863fb, 
     description: 'Jamies Restaurant', 
     __v: 0 }, 
     shape: { type: 'Point', coordinates: [ 2, 4 ] } }, 
    { _id: 'P4', 
     amenity: 'police', 
     info: null, 
     shape: { type: 'Point', coordinates: [ 4, 4 ] } }, 
    { _id: 'P1', 
     amenity: 'restaurant', 
     info: null, 
     shape: { type: 'Point', coordinates: [ 2, 2 ] } }, 
    { _id: 'P3', 
     amenity: 'police', 
     info: null, 
     shape: { type: 'Point', coordinates: [ 4, 2 ] } } 
] 

這是相當不錯的,並且是一種簡單的調用方法。趕上?令人遺憾地將操作員更改爲$geoNear考慮到球形幾何體會開始發生投擲錯誤。所以如果你想這樣做,那麼你就不能像以前那樣做事情。

雖然另一種方法是貓鼬有支持的.geoNear()函數。但是就像調用db.command一樣,這不會返回將接受.populate()的貓鼬文檔或其他模型類型對象。解?只需要輸出一點點:

var query = Shape.geoNear({ 
    "type": "Point", 
    "coordinates": [ 2, 4 ] 
},{spherical: true},function(err,shapes) { 
    if (err) throw err; 

    shapes = shapes.map(function(x) { 
    delete x.dis; 
    var a = new Shape(x.obj); 

    return a; 
    }); 
    Shape.populate(shapes, { path: "info" }, function(err,docs) { 
    if (err) throw err; 

    console.log(docs); 

    }); 

所以這裏返回的結果是一個原始對象的數組。但是通過一些操作,你可以把它們變成一些可以與.populate()方法一起工作的東西,它也可以從模型類中調用,如圖所示。

結果當然是一樣的,雖然現場順序可能有點不同。而且你不需要自己迭代查詢。這實際上只是.populate(),但我認爲我們可以同意使用.populate()方法至少看起來更清潔,並且不會爲此目的重新發明輪子。

+0

感謝一噸。你提示創建'new Shape()'然後使用'populate()'爲我打開新的大門! – ankitjaininfo

+0

請注意,這裏的「距離」會被丟棄。 –