तो इसे नए दिमाग से देख रहे हैं तो जवाब मेरे चेहरे पर घूर रहा है। मुख्य बात जो आपने पहले ही बता दी है वह यह है कि आप एक ही प्रतिक्रिया में दो प्रश्नों के "चौराहे" को खोजना चाहते हैं।
इसे देखने का एक और तरीका यह है कि आप चाहते हैं कि पहली क्वेरी से बंधे सभी बिंदु दूसरी क्वेरी के लिए "इनपुट" हों, और इसी तरह आवश्यकतानुसार। यह अनिवार्य रूप से एक प्रतिच्छेदन करता है, लेकिन तर्क वास्तव में शाब्दिक है।
तो बस एकत्रीकरण ढांचे का उपयोग करें मिलान करने वाले प्रश्नों को श्रृंखलाबद्ध करने के लिए। एक साधारण उदाहरण के लिए, निम्नलिखित दस्तावेज़ों पर विचार करें:
{ "loc" : { "type" : "Point", "coordinates" : [ 4, 4 ] } }
{ "loc" : { "type" : "Point", "coordinates" : [ 8, 8 ] } }
{ "loc" : { "type" : "Point", "coordinates" : [ 12, 12 ] } }
और जंजीर एकत्रीकरण पाइपलाइन, केवल दो प्रश्न:
db.geotest.aggregate([
{ "$match": {
"loc": {
"$geoWithin": {
"$box": [ [0,0], [10,10] ]
}
}
}},
{ "$match": {
"loc": {
"$geoWithin": {
"$box": [ [5,5], [20,20] ]
}
}
}}
])
इसलिए यदि आप तार्किक रूप से उस पर विचार करते हैं, तो पहला परिणाम उन बिंदुओं को खोजेगा जो प्रारंभिक बॉक्स या पहले दो आइटम की सीमा के भीतर आते हैं। फिर उन परिणामों पर दूसरी क्वेरी द्वारा कार्रवाई की जाती है, और चूंकि नई बॉक्स सीमाएं [5,5]
से शुरू होती हैं जिसमें पहला बिंदु शामिल नहीं है। तीसरे बिंदु को पहले ही बाहर कर दिया गया था, लेकिन यदि बॉक्स प्रतिबंधों को उलट दिया गया तो परिणाम वही मध्य दस्तावेज़ होगा।
यह कैसे काम करता है $geoWithin
विभिन्न अन्य भौगोलिक कार्यों की तुलना में क्वेरी ऑपरेटर:
तो परिणाम अच्छे और बुरे दोनों हैं। इसमें अच्छा है कि आप इस प्रकार के ऑपरेशन को बिना किसी इंडेक्स के कर सकते हैं, लेकिन बुरा है क्योंकि एक बार एग्रीगेशन पाइपलाइन ने पहले क्वेरी ऑपरेशन के बाद कलेक्शन के परिणामों को बदल दिया है, तो आगे कोई इंडेक्स इस्तेमाल नहीं किया जा सकता है। इसलिए किसी इंडेक्स का कोई भी प्रदर्शन लाभ प्रारंभिक पॉलीगॉन/मल्टीपॉलीगॉन के समर्थन के बाद किसी भी चीज़ से "सेट" परिणामों को मर्ज करने पर खो जाता है।
इस कारण से मैं अभी भी अनुशंसा करता हूं कि आप MongoDB को जारी क्वेरी के "बाहर" चौराहे की सीमा की गणना करें। भले ही पाइपलाइन की "जंजीर" प्रकृति के कारण एकत्रीकरण ढांचा ऐसा कर सकता है, और भले ही परिणामी चौराहे छोटे और छोटे हो जाएंगे, आपका सर्वश्रेष्ठ प्रदर्शन सही सीमाओं के साथ एक ही क्वेरी है जो सभी इंडेक्स लाभों का उपयोग कर सकता है।
ऐसा करने के लिए कई तरीके हैं, लेकिन संदर्भ के लिए यहां JSTS का उपयोग करके एक कार्यान्वयन है। पुस्तकालय, जो लोकप्रिय JTS का जावास्क्रिप्ट पोर्ट है। जावा के लिए पुस्तकालय। अन्य या अन्य भाषा पोर्ट हो सकते हैं, लेकिन इसमें सरल जियोसन पार्सिंग है और चौराहे की सीमा प्राप्त करने जैसी चीजों के लिए तरीकों में बनाया गया है:
var async = require('async');
util = require('util'),
jsts = require('jsts'),
mongo = require('mongodb'),
MongoClient = mongo.MongoClient;
var parser = new jsts.io.GeoJSONParser();
var polys= [
{
type: 'Polygon',
coordinates: [[
[ 0, 0 ], [ 0, 10 ], [ 10, 10 ], [ 10, 0 ], [ 0, 0 ]
]]
},
{
type: 'Polygon',
coordinates: [[
[ 5, 5 ], [ 5, 20 ], [ 20, 20 ], [ 20, 5 ], [ 5, 5 ]
]]
}
];
var points = [
{ type: 'Point', coordinates: [ 4, 4 ] },
{ type: 'Point', coordinates: [ 8, 8 ] },
{ type: 'Point', coordinates: [ 12, 12 ] }
];
MongoClient.connect('mongodb://localhost/test',function(err,db) {
db.collection('geotest',function(err,geo) {
if (err) throw err;
async.series(
[
// Insert some data
function(callback) {
var bulk = geo.initializeOrderedBulkOp();
bulk.find({}).remove();
async.each(points,function(point,callback) {
bulk.insert({ "loc": point });
callback();
},function(err) {
bulk.execute(callback);
});
},
// Run each version of the query
function(callback) {
async.parallel(
[
// Aggregation
function(callback) {
var pipeline = [];
polys.forEach(function(poly) {
pipeline.push({
"$match": {
"loc": {
"$geoWithin": {
"$geometry": poly
}
}
}
});
});
geo.aggregate(pipeline,callback);
},
// Using external set resolution
function(callback) {
var geos = polys.map(function(poly) {
return parser.read( poly );
});
var bounds = geos[0];
for ( var x=1; x<geos.length; x++ ) {
bounds = bounds.intersection( geos[x] );
}
var coords = parser.write( bounds );
geo.find({
"loc": {
"$geoWithin": {
"$geometry": coords
}
}
}).toArray(callback);
}
],
callback
);
}
],
function(err,results) {
if (err) throw err;
console.log(
util.inspect( results.slice(-1), false, 12, true ) );
db.close();
}
);
});
});
पूर्ण GeoJSON "बहुभुज" अभ्यावेदन का उपयोग करते हुए यह अनुवाद करता है कि JTS क्या समझ सकता है और इसके साथ काम कर सकता है। संभावना है कि वास्तविक आवेदन के लिए आपको प्राप्त होने वाला कोई भी इनपुट इस प्रारूप में होगा, साथ ही उपयुक्तता लागू करने के बजाय $box
।
तो यह एकत्रीकरण ढांचे के साथ किया जा सकता है, या यहां तक कि समानांतर प्रश्नों के परिणामों के "सेट" को विलय कर सकते हैं। लेकिन जहां एकत्रीकरण ढांचा बाहरी रूप से परिणामों के सेट को मर्ज करने से बेहतर कर सकता है, वहीं सर्वोत्तम परिणाम हमेशा पहले सीमा की गणना करने से आएंगे।