4

I am currently in the process of moving from MySQL to MongoDB for a site that I have been working on, and I am running into a strange issue.

I am trying to make the following collection:

country (string)
regions (array)
    regions (string)
    cities (array)
        city (string)

The problem is for some reason one of the cities array's is inserting as an object. Everything is coming from the same source and using the same code.

Example of issue:

[
    {
        country: "United States",
        regions: (array) [
            {
                region: "Arizona",
                cities: (array) [
                    { city: "Phoenix" }
                ]
            },
            {
                region: "California",
                cities: (object) [
                    { city: "Los Angeles" }
                ]
            }
        ]
    }
]

The reason this is an issue because when I when I search for { "regions.cities.city": "Los Angeles" } results come back as null, but if I search { "regions.cities.city": "Phoenix" } I get the proper results.

I hope this all makes sense, but feel free to ask questions.

-- EDIT --

PHP code generating the issue:

$countries = $this->db_model->find_list('countries', array(), false, true);
foreach($countries as $key => $country)
{
    if($regions = $this->db_model->find_list('regions', array('country_id' => $country['id']), false, true))
    {
        foreach($regions as $rkey => $region)
        {
            if($cities = $this->db_model->find_list('cities', array('region_id' => $region['id']), false, true))
            {
                $regions[$rkey]['cities'] = $cities;
            }
        }
        $countries[$key]['regions'] = $regions;
    }
}
$this->mongo->batch_insert('countries', $countries);
8
  • It's unclear how you do it. You need to provide a minimal, complete verifiable example: stackoverflow.com/help/mcve. What function you are using to generate the mentioned example. Commented Feb 13, 2019 at 19:02
  • I added a copy of the PHP code. Due to the fact that I am using CodeIgniter and the MongoDB PHP Library it's not % complete, but I hope if give a better idea of what is going on. If you need more, let me know. Commented Feb 13, 2019 at 19:26
  • 1
    So the problem is at mongo level. I noticed this info at docs: Note that you can have nested arrays and objects. The driver will always store an associative array as an object in the database. A numerically indexed array is stored as an array in case the keys start at 0 and are not interrupted, and as an object if the array keys don't start at 0 or have gaps (ie: 0, 1, 4, 5). php.net/manual/pt_BR/mongo.tutorial.insert.php Commented Feb 13, 2019 at 20:04
  • 1
    Your info helped me solve it. $regions[$rkey]['cities'] = array_values($cities); Commented Feb 13, 2019 at 20:11
  • 1
    I upvoted your comment, but I wasn't able to mark as solved since the solution is a post that I had to make myself. It says I have to wait 2 days to mark my own answer as solved. Commented Feb 13, 2019 at 20:20

1 Answer 1

4

Turns out the array keys needed to be reset do to the fact that I was deleting some items if they meet certain criteria (removed from example code to keep things easy to read, will include in code below).

$countries = $this->db_model->find_list('countries', array(), false, true);
foreach($countries as $key => $country)
{
    if($country['deleted']) { unset($countries[$key]); }
    elseif($regions = $this->db_model->find_list('regions', array('country_id' => $country['id']), false, true))
    {
        foreach($regions as $rkey => $region)
        {
            if($region['deleted']) { unset($regions[$rkey]); }
            elseif($cities = $this->db_model->find_list('cities', array('region_id' => $region['id']), false, true))
            {
                foreach($cities as $ckey => $city)
                {
                    if($city['deleted']) { unset($cities[$ckey]); }
                }
                $regions[$rkey]['cities'] =array_values($cities);
            }
        }
        $countries[$key]['regions'] = array_values($regions);
    }
}
$this->mongo->batch_insert('countries', array_values($countries));

Thank you Marco for all of your help and insight.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.