1. अवलोकन
इस ट्यूटोरियल में, हम MongoDB में भू-स्थानिक समर्थन का पता लगाएंगे।
हम चर्चा करेंगे कि भू-स्थानिक डेटा, भू-अनुक्रमण और भू-स्थानिक खोज को कैसे संग्रहीत किया जाए। हम अनेक भू-स्थानिक खोज क्वेरी का भी उपयोग करेंगे जैसे निकट , जियोविथिन , और geoIntersects ।
2. भू-स्थानिक डेटा संग्रहीत करना
सबसे पहले, आइए देखें कि MongoDB में भू-स्थानिक डेटा कैसे संग्रहीत करें।
MongoDB कई जियोसन का समर्थन करता है भू-स्थानिक डेटा संग्रहीत करने के लिए प्रकार। हमारे पूरे उदाहरणों में, हम मुख्य रूप से प्वाइंट . का उपयोग करेंगे और बहुभुज प्रकार।
2.1. बिंदु
यह सबसे बुनियादी और आम है जियोसन प्रकार, और इसका उपयोग ग्रिड पर एक विशिष्ट बिंदु को दर्शाने के लिए किया जाता है ।
यहाँ, हमारे पास एक साधारण वस्तु है, हमारे स्थानों . में संग्रह, जिसमें फ़ील्ड स्थान . है एक बिंदु . के रूप में :
{
"name": "Big Ben",
"location": {
"coordinates": [-0.1268194, 51.5007292],
"type": "Point"
}
}
ध्यान दें कि देशांतर मान पहले आता है, फिर अक्षांश।
2.2. बहुभुज
बहुभुज थोड़ा अधिक जटिल है GeoJSON टाइप करें।
हम बहुभुज का उपयोग कर सकते हैं किसी क्षेत्र को उसकी बाहरी सीमाओं के साथ परिभाषित करने के लिए और यदि आवश्यक हो तो आंतरिक छेद भी।
आइए एक और वस्तु देखते हैं जिसका स्थान बहुभुज . के रूप में परिभाषित है :
{
"name": "Hyde Park",
"location": {
"coordinates": [
[
[-0.159381, 51.513126],
[-0.189615, 51.509928],
[-0.187373, 51.502442],
[-0.153019, 51.503464],
[-0.159381, 51.513126]
]
],
"type": "Polygon"
}
}
इस उदाहरण में, हमने बाहरी सीमाओं का प्रतिनिधित्व करने वाले बिंदुओं की एक सरणी परिभाषित की है। हमें बाउंड को भी बंद करना होगा ताकि अंतिम बिंदु पहले बिंदु के बराबर हो।
ध्यान दें कि हमें बाहरी सीमा बिंदुओं को वामावर्त दिशा में और होल बाउंड को दक्षिणावर्त दिशा में परिभाषित करने की आवश्यकता है।
इन प्रकारों के अलावा, कई अन्य प्रकार भी हैं जैसे LineString, मल्टीपॉइंट, मल्टीपॉलीगॉन, मल्टीलाइनस्ट्रिंग, और ज्यामिति संग्रह।
3. भू-स्थानिक अनुक्रमण
हमारे द्वारा संग्रहीत भू-स्थानिक डेटा पर खोज क्वेरी करने के लिए, हमें अपने स्थान पर एक भू-स्थानिक अनुक्रमणिका बनाने की आवश्यकता है फ़ील्ड.
हमारे पास मूल रूप से दो विकल्प हैं:2d और 2dsphere ।
लेकिन पहले, आइए अपने स्थानों collection . को परिभाषित करें :
MongoClient mongoClient = new MongoClient();
MongoDatabase db = mongoClient.getDatabase("myMongoDb");
collection = db.getCollection("places");
3.1. 2d भू-स्थानिक सूचकांक
2d अनुक्रमणिका हमें 2d समतल गणनाओं के आधार पर काम करने वाली खोज क्वेरी करने में सक्षम बनाती है।
हम एक 2d बना सकते हैं स्थान . पर अनुक्रमणिका हमारे जावा एप्लिकेशन में फ़ील्ड निम्नानुसार है:
collection.createIndex(Indexes.geo2d("location"));
बेशक, हम मोंगो . में भी ऐसा ही कर सकते हैं खोल:
db.places.createIndex({location:"2d"})
3.2. 2dsphere भू-स्थानिक सूचकांक
2dsphere अनुक्रमणिका उन प्रश्नों का समर्थन करती है जो गोलाकार गणनाओं के आधार पर काम करते हैं।
इसी तरह, हम एक 2dsphere बना सकते हैं जावा में अनुक्रमणिका समान अनुक्रमणिका . का उपयोग करते हुए ऊपर के रूप में कक्षा:
collection.createIndex(Indexes.geo2dsphere("location"));
या मोंगो . में खोल:
db.places.createIndex({location:"2dsphere"})
4. भू-स्थानिक प्रश्नों का उपयोग करके खोजना
अब, रोमांचक भाग के लिए, आइए भू-स्थानिक प्रश्नों का उपयोग करके वस्तुओं को उनके स्थान के आधार पर खोजें।
4.1. क्वेरी के पास
आइए निकट से प्रारंभ करें। हम निकट का उपयोग कर सकते हैं एक निश्चित दूरी के भीतर स्थानों को खोजने के लिए क्वेरी।
निकट क्वेरी 2d . दोनों के साथ काम करती है और 2dsphere सूचकांक.
अगले उदाहरण में, हम उन स्थानों की खोज करेंगे जो दिए गए स्थान से 1 किमी से कम और 10 मीटर से अधिक दूर हैं:
@Test
public void givenNearbyLocation_whenSearchNearby_thenFound() {
Point currentLoc = new Point(new Position(-0.126821, 51.495885));
FindIterable<Document> result = collection.find(
Filters.near("location", currentLoc, 1000.0, 10.0));
assertNotNull(result.first());
assertEquals("Big Ben", result.first().get("name"));
}
और मोंगो . में संबंधित क्वेरी खोल:
db.places.find({
location: {
$near: {
$geometry: {
type: "Point",
coordinates: [-0.126821, 51.495885]
},
$maxDistance: 1000,
$minDistance: 10
}
}
})
ध्यान दें कि परिणाम निकटतम से सबसे दूर तक क्रमबद्ध हैं।
इसी तरह, यदि हम बहुत दूर के स्थान का उपयोग करते हैं, तो हमें आस-पास कोई स्थान नहीं मिलेगा:
@Test
public void givenFarLocation_whenSearchNearby_thenNotFound() {
Point currentLoc = new Point(new Position(-0.5243333, 51.4700223));
FindIterable<Document> result = collection.find(
Filters.near("location", currentLoc, 5000.0, 10.0));
assertNull(result.first());
}
हमारे पास नियरस्फेयर . भी है विधि, जो बिल्कुल निकट, . की तरह कार्य करती है सिवाय इसके कि यह गोलाकार ज्यामिति का उपयोग करके दूरी की गणना करता है।
4.2. क्वेरी के भीतर
इसके बाद, हम geoWithin . को एक्सप्लोर करेंगे क्वेरी।
द जियोइनथिन क्वेरी हमें उन स्थानों की खोज करने में सक्षम बनाती है जो किसी दिए गए ज्यामिति . के भीतर पूरी तरह से मौजूद हैं , एक वृत्त, बॉक्स या बहुभुज की तरह। यह दोनों 2d . के साथ भी काम करता है और 2dsphere सूचकांक।
इस उदाहरण में, हम उन स्थानों की तलाश कर रहे हैं जो दिए गए केंद्र की स्थिति से 5 किमी के दायरे में मौजूद हैं:
@Test
public void givenNearbyLocation_whenSearchWithinCircleSphere_thenFound() {
double distanceInRad = 5.0 / 6371;
FindIterable<Document> result = collection.find(
Filters.geoWithinCenterSphere("location", -0.1435083, 51.4990956, distanceInRad));
assertNotNull(result.first());
assertEquals("Big Ben", result.first().get("name"));
}
ध्यान दें कि हमें दूरी को किमी से रेडियन में बदलने की आवश्यकता है (बस पृथ्वी की त्रिज्या से विभाजित करें)।
और परिणामी क्वेरी:
db.places.find({
location: {
$geoWithin: {
$centerSphere: [
[-0.1435083, 51.4990956],
0.0007848061528802386
]
}
}
})
इसके बाद, हम आयत "बॉक्स" के भीतर मौजूद सभी स्थानों की खोज करेंगे। हमें बॉक्स को उसके निचले बाएँ स्थान और ऊपरी दाएँ स्थान द्वारा परिभाषित करने की आवश्यकता है:
@Test
public void givenNearbyLocation_whenSearchWithinBox_thenFound() {
double lowerLeftX = -0.1427638;
double lowerLeftY = 51.4991288;
double upperRightX = -0.1256209;
double upperRightY = 51.5030272;
FindIterable<Document> result = collection.find(
Filters.geoWithinBox("location", lowerLeftX, lowerLeftY, upperRightX, upperRightY));
assertNotNull(result.first());
assertEquals("Big Ben", result.first().get("name"));
}
mongo . में संबंधित क्वेरी यहां दी गई है खोल:
db.places.find({
location: {
$geoWithin: {
$box: [
[-0.1427638, 51.4991288],
[-0.1256209, 51.5030272]
]
}
}
})
अंत में, यदि हम जिस क्षेत्र में खोज करना चाहते हैं वह आयत या वृत्त नहीं है, तो हम अधिक विशिष्ट क्षेत्र को परिभाषित करने के लिए बहुभुज का उपयोग कर सकते हैं :
@Test
public void givenNearbyLocation_whenSearchWithinPolygon_thenFound() {
ArrayList<List<Double>> points = new ArrayList<List<Double>>();
points.add(Arrays.asList(-0.1439, 51.4952));
points.add(Arrays.asList(-0.1121, 51.4989));
points.add(Arrays.asList(-0.13, 51.5163));
points.add(Arrays.asList(-0.1439, 51.4952));
FindIterable<Document> result = collection.find(
Filters.geoWithinPolygon("location", points));
assertNotNull(result.first());
assertEquals("Big Ben", result.first().get("name"));
}
और यहाँ संबंधित क्वेरी है:
db.places.find({
location: {
$geoWithin: {
$polygon: [
[-0.1439, 51.4952],
[-0.1121, 51.4989],
[-0.13, 51.5163],
[-0.1439, 51.4952]
]
}
}
})
हमने केवल एक बहुभुज को इसकी बाहरी सीमाओं के साथ परिभाषित किया है, लेकिन हम इसमें छेद भी जोड़ सकते हैं। प्रत्येक छेद एक सूची होगा बिंदु . का रों:
geoWithinPolygon("location", points, hole1, hole2, ...)
4.3. इंटरसेक्ट क्वेरी
अंत में, आइए देखें geoIntersects क्वेरी।
द जियो इंटरसेक्ट्स क्वेरी उन वस्तुओं को ढूंढती है जो कम से कम किसी दिए गए ज्यामिति के साथ प्रतिच्छेद करती हैं। तुलना करके, geoWithin किसी दिए गए ज्यामिति . में पूरी तरह से मौजूद वस्तुओं को ढूंढता है ।
यह क्वेरी 2dsphere . के साथ काम करती है केवल अनुक्रमणिका।
आइए इसे व्यावहारिक रूप से देखें, उदाहरण के लिए किसी ऐसे स्थान की तलाश करना जो बहुभुज से प्रतिच्छेद करता हो :
@Test
public void givenNearbyLocation_whenSearchUsingIntersect_thenFound() {
ArrayList<Position> positions = new ArrayList<Position>();
positions.add(new Position(-0.1439, 51.4952));
positions.add(new Position(-0.1346, 51.4978));
positions.add(new Position(-0.2177, 51.5135));
positions.add(new Position(-0.1439, 51.4952));
Polygon geometry = new Polygon(positions);
FindIterable<Document> result = collection.find(
Filters.geoIntersects("location", geometry));
assertNotNull(result.first());
assertEquals("Hyde Park", result.first().get("name"));
}
परिणामी क्वेरी:
db.places.find({
location:{
$geoIntersects:{
$geometry:{
type:"Polygon",
coordinates:[
[
[-0.1439, 51.4952],
[-0.1346, 51.4978],
[-0.2177, 51.5135],
[-0.1439, 51.4952]
]
]
}
}
}
})