> ## Documentation Index
> Fetch the complete documentation index at: https://docs.countrystatecity.in/llms.txt
> Use this file to discover all available pages before exploring further.

# MongoDB Installation

> Complete guide to installing the Countries States Cities database in MongoDB with document-oriented data structure

MongoDB is a popular document-oriented NoSQL database that stores data in flexible, JSON-like documents. This guide covers installing the Countries States Cities database in MongoDB using the provided BSON dump files.

<Info>
  MongoDB installation typically takes 2-4 minutes and requires approximately 180MB of disk space.
</Info>

## Prerequisites

Before starting, ensure you have:

* MongoDB 4.0+ installed (MongoDB 5.0+ recommended)
* MongoDB server running on your system
* At least 300MB free disk space
* Downloaded the `mongodb-dump/world-mongodb-dump.tar.gz` file from our [GitHub repository](https://github.com/dr5hn/countries-states-cities-database)

<Note>
  MongoDB uses BSON (Binary JSON) format rather than SQL, so the installation process differs from relational databases.
</Note>

## Installation Steps

<Steps>
  <Step title="Extract MongoDB Archive">
    ```bash theme={null}
    tar -xzvf mongodb-dump/world-mongodb-dump.tar.gz
    ```

    This extracts the MongoDB dump files to a `mongodb-dump/world` directory containing:

    * `regions.bson` and `regions.metadata.json`
    * `countries.bson` and `countries.metadata.json`
    * `states.bson` and `states.metadata.json`
    * `cities.bson` and `cities.metadata.json`
  </Step>

  <Step title="Restore Database">
    ```bash theme={null}
    mongorestore --host localhost:27017 --db world mongodb-dump/world
    ```

    <Info>
      Adjust the host and port parameters according to your MongoDB configuration. Default is usually localhost:27017.
    </Info>
  </Step>

  <Step title="Verify Installation">
    ```bash theme={null}
    mongo world --eval "
    printjson({
      regions: db.regions.count(),
      countries: db.countries.count(),  
      states: db.states.count(),
      cities: db.cities.count()
    })
    "
    ```

    Expected output:

    ```json theme={null}
    {
      "regions": 5,
      "countries": 250,
      "states": 5299,
      "cities": 153765
    }
    ```
  </Step>
</Steps>

## Alternative Installation Methods

### Using MongoDB Compass

<Steps>
  <Step title="Connect to Database">
    Open MongoDB Compass and connect to your MongoDB server.
  </Step>

  <Step title="Create Database">
    * Click "Create Database"
    * Database Name: "world"
    * Collection Name: "countries" (initial collection)
  </Step>

  <Step title="Import Collections">
    For each collection (regions, countries, states, cities):

    * Select the collection
    * Click "ADD DATA" → "Import File"
    * Choose the corresponding `.json` file
    * Select JSON format and import
  </Step>
</Steps>

### Using Docker

<Steps>
  <Step title="Run MongoDB Container">
    ```bash theme={null}
    docker run -d \
      --name mongodb-csc \
      -p 27017:27017 \
      -v $(pwd)/mongodb-data:/data/db \
      mongo:5.0
    ```
  </Step>

  <Step title="Copy Dump Files">
    ```bash theme={null}
    docker cp mongodb-dump/world mongodb-csc:/tmp/world
    ```
  </Step>

  <Step title="Restore Inside Container">
    ```bash theme={null}
    docker exec mongodb-csc mongorestore --db world /tmp/world
    ```
  </Step>
</Steps>

## Database Structure

MongoDB stores the data in four main collections:

<CodeGroup>
  ```javascript Regions Collection theme={null}
  // Sample region document
  {
    "_id": ObjectId("..."),
    "id": 1,
    "name": "Africa",
    "subregions": [
      "Northern Africa",
      "Western Africa", 
      "Eastern Africa",
      "Southern Africa",
      "Middle Africa"
    ]
  }
  ```

  ```javascript Countries Collection theme={null}
  // Sample country document
  {
    "_id": ObjectId("..."),
    "id": 1,
    "name": "Afghanistan",
    "iso3": "AFG",
    "iso2": "AF",
    "numeric_code": "004",
    "phone_code": "93",
    "capital": "Kabul",
    "currency": "AFN",
    "currency_name": "Afghan afghani",
    "currency_symbol": "؋",
    "tld": ".af",
    "native": "افغانستان",
    "region": "Asia",
    "subregion": "Southern Asia",
    "timezones": [
      {
        "zoneName": "Asia/Kabul",
        "gmtOffset": 16200,
        "gmtOffsetName": "UTC+04:30"
      }
    ],
    "latitude": "33.00000000",
    "longitude": "65.00000000"
  }
  ```

  ```javascript Cities Collection theme={null}
  // Sample city document
  {
    "_id": ObjectId("..."),
    "id": 1,
    "name": "New York",
    "state_id": 3176,
    "state_code": "NY",
    "state_name": "New York",
    "country_id": 233,
    "country_code": "US",
    "country_name": "United States",
    "latitude": "40.71427000",
    "longitude": "-74.00597000",
    "wikiDataId": "Q60"
  }
  ```
</CodeGroup>

## MongoDB-Specific Operations

### Basic Queries

<CodeGroup>
  ```javascript Find Operations theme={null}
  // Connect to the database
  use world

  // Find all countries in Europe
  db.countries.find({"region": "Europe"}).limit(5)

  // Find cities in California
  db.cities.find({
    "country_code": "US",
    "state_code": "CA"
  }).limit(10)

  // Find countries with specific currency
  db.countries.find({"currency": "USD"})

  // Find cities by coordinates (nearby locations)
  db.cities.find({
    "latitude": {$gte: "40", $lte: "41"},
    "longitude": {$gte: "-74", $lte: "-73"}
  })
  ```

  ```javascript Aggregation Queries theme={null}
  // Count cities by country
  db.cities.aggregate([
    { $group: { _id: "$country_name", count: { $sum: 1 } } },
    { $sort: { count: -1 } },
    { $limit: 10 }
  ])

  // Average coordinates by region
  db.cities.aggregate([
    {
      $lookup: {
        from: "countries",
        localField: "country_code",
        foreignField: "iso2", 
        as: "country_info"
      }
    },
    { $unwind: "$country_info" },
    {
      $group: {
        _id: "$country_info.region",
        avgLat: { $avg: { $toDouble: "$latitude" } },
        avgLng: { $avg: { $toDouble: "$longitude" } },
        count: { $sum: 1 }
      }
    }
  ])

  // Cities with timezone information
  db.cities.aggregate([
    {
      $lookup: {
        from: "countries",
        localField: "country_code", 
        foreignField: "iso2",
        as: "country"
      }
    },
    { $unwind: "$country" },
    { $unwind: "$country.timezones" },
    {
      $project: {
        name: 1,
        country_name: 1,
        timezone: "$country.timezones.zoneName",
        gmtOffset: "$country.timezones.gmtOffset"
      }
    },
    { $limit: 10 }
  ])
  ```
</CodeGroup>

### Create Indexes

<Steps>
  <Step title="Basic Indexes">
    ```javascript theme={null}
    // Essential indexes for query performance
    db.countries.createIndex({"iso2": 1})
    db.countries.createIndex({"iso3": 1})
    db.countries.createIndex({"region": 1})
    db.countries.createIndex({"subregion": 1})

    db.states.createIndex({"country_id": 1})
    db.states.createIndex({"country_code": 1})

    db.cities.createIndex({"state_id": 1})
    db.cities.createIndex({"country_id": 1})
    db.cities.createIndex({"country_code": 1})
    db.cities.createIndex({"state_code": 1})
    ```
  </Step>

  <Step title="Geospatial Indexes">
    ```javascript theme={null}
    // Create 2dsphere index for geospatial queries
    db.cities.createIndex({
      "location": "2dsphere"
    })

    // Add location field to existing documents
    db.cities.updateMany(
      {},
      [{
        $set: {
          location: {
            type: "Point",
            coordinates: [
              { $toDouble: "$longitude" },
              { $toDouble: "$latitude" }
            ]
          }
        }
      }]
    )
    ```
  </Step>

  <Step title="Text Search Indexes">
    ```javascript theme={null}
    // Create text indexes for search functionality
    db.countries.createIndex({
      "name": "text",
      "native": "text",
      "capital": "text"
    })

    db.cities.createIndex({
      "name": "text",
      "state_name": "text",
      "country_name": "text"
    })
    ```
  </Step>
</Steps>

## Connection Examples

<Tabs>
  <Tab title="Python (PyMongo)">
    ```python theme={null}
    from pymongo import MongoClient
    from pprint import pprint
    import json

    class WorldDatabase:
        def __init__(self, connection_string="mongodb://localhost:27017/"):
            self.client = MongoClient(connection_string)
            self.db = self.client.world
            
        def get_countries(self, region=None, limit=None):
            query = {}
            if region:
                query["region"] = region
                
            cursor = self.db.countries.find(query)
            if limit:
                cursor = cursor.limit(limit)
                
            return list(cursor)
        
        def get_cities_by_country(self, country_code, limit=None):
            query = {"country_code": country_code}
            cursor = self.db.cities.find(query)
            if limit:
                cursor = cursor.limit(limit)
            return list(cursor)
        
        def search_cities(self, search_term, limit=10):
            # Using text search
            return list(self.db.cities.find(
                {"$text": {"$search": search_term}},
                {"score": {"$meta": "textScore"}}
            ).sort([("score", {"$meta": "textScore"})]).limit(limit))
        
        def find_nearby_cities(self, longitude, latitude, max_distance=100000):
            # Geospatial query (requires 2dsphere index on location field)
            return list(self.db.cities.find({
                "location": {
                    "$near": {
                        "$geometry": {
                            "type": "Point",
                            "coordinates": [longitude, latitude]
                        },
                        "$maxDistance": max_distance
                    }
                }
            }))
        
        def get_country_statistics(self):
            pipeline = [
                {
                    "$group": {
                        "_id": "$region",
                        "countries": {"$sum": 1},
                        "currencies": {"$addToSet": "$currency"}
                    }
                },
                {"$sort": {"countries": -1}}
            ]
            return list(self.db.countries.aggregate(pipeline))
        
        def close(self):
            self.client.close()

    # Usage example
    db = WorldDatabase()

    try:
        # Get European countries
        europe_countries = db.get_countries(region="Europe", limit=5)
        print("European Countries:")
        for country in europe_countries:
            print(f"  {country['name']} ({country['iso2']})")
        
        # Get US cities
        us_cities = db.get_cities_by_country("US", limit=5)
        print(f"\nUS Cities:")
        for city in us_cities:
            print(f"  {city['name']}, {city['state_name']}")
        
        # Search cities
        search_results = db.search_cities("paris", limit=5)
        print(f"\nCities matching 'paris':")
        for city in search_results:
            print(f"  {city['name']}, {city['country_name']}")
        
        # Country statistics
        stats = db.get_country_statistics()
        print(f"\nCountries by region:")
        for stat in stats:
            print(f"  {stat['_id']}: {stat['countries']} countries")

    finally:
        db.close()
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    const { MongoClient } = require('mongodb');

    class WorldDatabase {
        constructor(connectionString = 'mongodb://localhost:27017') {
            this.connectionString = connectionString;
            this.client = null;
            this.db = null;
        }
        
        async connect() {
            this.client = new MongoClient(this.connectionString);
            await this.client.connect();
            this.db = this.client.db('world');
        }
        
        async getCountries(region = null, limit = null) {
            const query = region ? { region } : {};
            let cursor = this.db.collection('countries').find(query);
            if (limit) cursor = cursor.limit(limit);
            return await cursor.toArray();
        }
        
        async getCitiesByCountry(countryCode, limit = null) {
            const query = { country_code: countryCode };
            let cursor = this.db.collection('cities').find(query);
            if (limit) cursor = cursor.limit(limit);
            return await cursor.toArray();
        }
        
        async searchCities(searchTerm, limit = 10) {
            return await this.db.collection('cities')
                .find(
                    { $text: { $search: searchTerm } },
                    { projection: { score: { $meta: 'textScore' } } }
                )
                .sort({ score: { $meta: 'textScore' } })
                .limit(limit)
                .toArray();
        }
        
        async findNearbyCities(longitude, latitude, maxDistance = 100000) {
            return await this.db.collection('cities').find({
                location: {
                    $near: {
                        $geometry: {
                            type: "Point",
                            coordinates: [longitude, latitude]
                        },
                        $maxDistance: maxDistance
                    }
                }
            }).toArray();
        }
        
        async getCountryStatistics() {
            const pipeline = [
                {
                    $group: {
                        _id: "$region",
                        countries: { $sum: 1 },
                        currencies: { $addToSet: "$currency" }
                    }
                },
                { $sort: { countries: -1 } }
            ];
            
            return await this.db.collection('countries').aggregate(pipeline).toArray();
        }
        
        async close() {
            if (this.client) {
                await this.client.close();
            }
        }
    }

    // Usage example
    async function example() {
        const db = new WorldDatabase();
        
        try {
            await db.connect();
            
            // Get European countries
            const europeCountries = await db.getCountries('Europe', 5);
            console.log('European Countries:');
            europeCountries.forEach(country => {
                console.log(`  ${country.name} (${country.iso2})`);
            });
            
            // Get US cities
            const usCities = await db.getCitiesByCountry('US', 5);
            console.log('\nUS Cities:');
            usCities.forEach(city => {
                console.log(`  ${city.name}, ${city.state_name}`);
            });
            
            // Search cities
            const searchResults = await db.searchCities('paris', 5);
            console.log('\nCities matching "paris":');
            searchResults.forEach(city => {
                console.log(`  ${city.name}, ${city.country_name}`);
            });
            
            // Country statistics
            const stats = await db.getCountryStatistics();
            console.log('\nCountries by region:');
            stats.forEach(stat => {
                console.log(`  ${stat._id}: ${stat.countries} countries`);
            });
            
        } catch (error) {
            console.error('Database error:', error);
        } finally {
            await db.close();
        }
    }

    example();
    ```
  </Tab>

  <Tab title="Java (Spring Data)">
    ```java theme={null}
    import org.springframework.data.mongodb.core.MongoTemplate;
    import org.springframework.data.mongodb.core.query.Criteria;
    import org.springframework.data.mongodb.core.query.Query;
    import org.springframework.data.mongodb.core.query.TextCriteria;
    import org.springframework.data.mongodb.core.query.TextQuery;
    import org.springframework.data.geo.Distance;
    import org.springframework.data.geo.Metrics;
    import org.springframework.data.geo.Point;
    import org.springframework.data.mongodb.core.query.NearQuery;

    import java.util.List;

    public class WorldDatabase {
        
        private final MongoTemplate mongoTemplate;
        
        public WorldDatabase(MongoTemplate mongoTemplate) {
            this.mongoTemplate = mongoTemplate;
        }
        
        public List<Country> getCountries(String region, Integer limit) {
            Query query = new Query();
            if (region != null) {
                query.addCriteria(Criteria.where("region").is(region));
            }
            if (limit != null) {
                query.limit(limit);
            }
            return mongoTemplate.find(query, Country.class, "countries");
        }
        
        public List<City> getCitiesByCountry(String countryCode, Integer limit) {
            Query query = new Query(Criteria.where("country_code").is(countryCode));
            if (limit != null) {
                query.limit(limit);
            }
            return mongoTemplate.find(query, City.class, "cities");
        }
        
        public List<City> searchCities(String searchTerm, int limit) {
            TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny(searchTerm);
            Query query = TextQuery.queryText(criteria).sortByScore().limit(limit);
            return mongoTemplate.find(query, City.class, "cities");
        }
        
        public List<City> findNearbyCities(double longitude, double latitude, double maxDistanceKm) {
            Point location = new Point(longitude, latitude);
            Distance distance = new Distance(maxDistanceKm, Metrics.KILOMETERS);
            Query query = new Query(Criteria.where("location").near(location).maxDistance(distance.getNormalizedValue()));
            return mongoTemplate.find(query, City.class, "cities");
        }
    }

    // Entity classes
    @Document(collection = "countries")
    public class Country {
        @Id
        private String id;
        private String name;
        private String iso2;
        private String iso3;
        private String region;
        private String subregion;
        private String capital;
        private String currency;
        private String phone_code;
        
        // Getters and setters...
    }

    @Document(collection = "cities") 
    public class City {
        @Id
        private String id;
        private String name;
        private String state_name;
        private String country_name;
        private String country_code;
        private String state_code;
        private String latitude;
        private String longitude;
        
        // Getters and setters...
    }
    ```
  </Tab>
</Tabs>

## Advanced Features

### Geospatial Queries

<CodeGroup>
  ```javascript Setup Geospatial Data theme={null}
  // Add GeoJSON location field to all cities
  db.cities.updateMany(
    {},
    [{
      $set: {
        location: {
          type: "Point",
          coordinates: [
            { $toDouble: "$longitude" },
            { $toDouble: "$latitude" }
          ]
        }
      }
    }]
  )

  // Create 2dsphere index
  db.cities.createIndex({ "location": "2dsphere" })
  ```

  ```javascript Geospatial Queries theme={null}
  // Find cities within 50km of New York
  db.cities.find({
    location: {
      $near: {
        $geometry: {
          type: "Point",
          coordinates: [-74.006, 40.7128]
        },
        $maxDistance: 50000
      }
    }
  })

  // Find cities within a polygon (e.g., a country boundary)
  db.cities.find({
    location: {
      $geoWithin: {
        $geometry: {
          type: "Polygon",
          coordinates: [[
            [-74.0, 40.7], [-74.0, 40.8], 
            [-73.9, 40.8], [-73.9, 40.7], 
            [-74.0, 40.7]
          ]]
        }
      }
    }
  })
  ```
</CodeGroup>

### Data Validation

```javascript theme={null}
// Add validation rules
db.createCollection("countries", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["name", "iso2", "iso3"],
      properties: {
        name: {
          bsonType: "string",
          description: "must be a string and is required"
        },
        iso2: {
          bsonType: "string", 
          minLength: 2,
          maxLength: 2,
          description: "must be a 2-character string"
        },
        iso3: {
          bsonType: "string",
          minLength: 3, 
          maxLength: 3,
          description: "must be a 3-character string"
        }
      }
    }
  }
})
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Connection Refused">
    **Problem**: `MongoNetworkError: connect ECONNREFUSED`

    **Solutions**:

    1. Check if MongoDB service is running: `sudo systemctl status mongod`
    2. Start MongoDB: `sudo systemctl start mongod`
    3. Check MongoDB port: `netstat -an | grep 27017`
    4. Verify connection string format
    5. Check firewall settings
  </Accordion>

  <Accordion title="Authentication Failed">
    **Problem**: `MongoServerError: Authentication failed`

    **Solutions**:

    1. Check username/password in connection string
    2. Verify user exists: `db.getUsers()`
    3. Check user roles: `db.getUser("username")`
    4. Create user with proper permissions:
       ```javascript theme={null}
       use admin
       db.createUser({
         user: "worlduser",
         pwd: "password",
         roles: [{ role: "readWrite", db: "world" }]
       })
       ```
  </Accordion>

  <Accordion title="Import Errors">
    **Problem**: `mongorestore` fails with various errors

    **Solutions**:

    1. Check MongoDB version compatibility
    2. Ensure sufficient disk space
    3. Verify dump file integrity: `tar -tzf world-mongodb-dump.tar.gz`
    4. Try importing individual collections:
       ```bash theme={null}
       mongorestore --db world --collection countries mongodb-dump/world/countries.bson
       ```
    5. Use `--drop` flag to overwrite existing data
  </Accordion>

  <Accordion title="Performance Issues">
    **Problem**: Queries are running slowly

    **Solutions**:

    1. Create appropriate indexes (see Performance section)
    2. Use `explain()` to analyze query performance
    3. Optimize aggregation pipelines
    4. Increase MongoDB cache size
    5. Consider sharding for very large datasets
  </Accordion>
</AccordionGroup>

## Backup and Maintenance

### Backup Strategies

<CodeGroup>
  ```bash Complete Database Backup theme={null}
  #!/bin/bash
  # backup_world_mongodb.sh

  DATE=$(date +%Y%m%d_%H%M%S)
  BACKUP_DIR="/path/to/backups"
  DB_NAME="world"

  # Create dump
  mongodump --host localhost:27017 --db $DB_NAME --out "$BACKUP_DIR/mongodb_backup_$DATE"

  # Compress backup
  tar -czf "$BACKUP_DIR/world_mongodb_backup_$DATE.tar.gz" -C "$BACKUP_DIR" "mongodb_backup_$DATE"

  # Remove uncompressed files
  rm -rf "$BACKUP_DIR/mongodb_backup_$DATE"

  # Keep only last 7 backups
  find $BACKUP_DIR -name "world_mongodb_backup_*.tar.gz" -type f -mtime +7 -delete

  echo "Backup completed: world_mongodb_backup_$DATE.tar.gz"
  ```

  ```bash Collection-Specific Backup theme={null}
  # Backup specific collections
  mongodump --db world --collection countries --out backup_countries
  mongodump --db world --collection cities --out backup_cities

  # Restore specific collection
  mongorestore --db world --collection countries backup_countries/world/countries.bson
  ```
</CodeGroup>

### Maintenance Tasks

```javascript theme={null}
// Check collection statistics
db.countries.stats()
db.cities.stats()

// Rebuild indexes
db.countries.reIndex()
db.cities.reIndex()

// Check index usage
db.cities.aggregate([{ $indexStats: {} }])

// Compact collections (offline operation)
db.runCommand({ compact: "cities" })
```

<Tip>
  MongoDB automatically manages most maintenance tasks, but periodic index optimization and backup verification are recommended.
</Tip>

## Next Steps

After successful installation:

1. **Create appropriate indexes** for your query patterns
2. **Set up replica sets** for high availability
3. **Configure sharding** if handling very large datasets
4. **Implement monitoring** with MongoDB Compass or third-party tools
5. **Set up automated backups** using the provided scripts

<Card title="Need Help?" icon="support">
  Join our [community discussions](https://github.com/dr5hn/countries-states-cities-database/discussions) for MongoDB-specific questions and NoSQL optimization tips.
</Card>
