Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add data inside documents in Mongo DB using PHP

Tags:

php

mongodb

I want to insert data in Mongo database using PHP script, in year wise documents so that it may look like this (All years in one document);

cars{
        2017{
            car=Motorolla
            color = blue
        }
        2016{
            car=Toyota
            color = green
        }
        2015{
            car=Corolla
            color = black
        }
    }

I wanted to add the document but it prompts

Document can't have $ prefixed field names: $years[0]

Is it possible to make such schema in Mongo using PHP?

Code

<?php
    try {        
        $car = 'Motorolla';
        $color = 'blue';

        //$car = 'Toyota';
        //$color = 'green';

        //$car = 'Corolla';
        //$color = 'black';

        $years = array(2017, 2016, 2015);       
        $manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
        $bulkWriteManager = new MongoDB\Driver\BulkWrite;
        $document = ['_id' => new MongoDB\BSON\ObjectID, '$years[0]' => $car, '$years[1]' => $color];   // Making a query type

        try {
            $bulkWriteManager->insert($document);   // Inserting Document
            echo 1;           
        } catch(MongoCursorException $e) {
            /* handle the exception */
            echo 0;
        }

        $manager->executeBulkWrite('dbName.carsCol', $bulkWriteManager);  // Going to DB and Collection

    } catch (MongoDB\Driver\Exception\Exception $e) {
        $filename = basename(__FILE__);
        echo "The $filename script has experienced an error.\n"; 
        echo "It failed with the following exception:\n";       
        echo "Exception:", $e->getMessage(), "\n";


    }

?>

I do not want to add whole car object at once. I want to add Year object every time. Any help will be appreciable. OR Any relative answer so that I may get the data from Mongo Database according to the year?

Edit1

For first time creation. - Credits goes to @Veeram

<?php
    try {        
        $car = 'Malibu';
        $color = 'red';
        $years = array(2017);       

        $manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
        $bulkWriteManager = new MongoDB\Driver\BulkWrite;
        //{"car":"chevy", "color":"black", year: 2017}
        $insert = ['car' => $car, 'color' => $color, 'year' => $years[0]];
        try {
            $bulkWriteManager -> insert($insert); // Inserting Document
            echo 1;
        } catch (MongoCursorException $e) {
            echo 0;
        }
        $manager->executeBulkWrite('dbName.mycol', $bulkWriteManager);  // Going to DB and Collection           
    } catch (MongoDB\Driver\Exception\Exception $e) {
        $filename = basename(__FILE__);
        echo "The $filename script has experienced an error.\n"; 
        echo "It failed with the following exception:\n";       
        echo "Exception:", $e->getMessage(), "\n";
        echo "In file:", $e->getFile(), "\n";
        echo "On line:", $e->getLine(), "\n";    
    }
?>

For the updation- Credits goes to @Veeram

<?php
    try {        
        $car = 'ChangedCar';
        $color = 'changedColor';
        $years = array(2017);

        $manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
        $bulkWriteManager = new MongoDB\Driver\BulkWrite;

        $query = ['cars.year' => $years[0]]; 

        //{ $push: { "cars.$.data": { "car":"chevy", "color":"black"} }}
        $update = ['$push'=> ['cars.$.data'=>['car' => $car, 'color' => $color]]];
        try {
            $bulkWriteManager->update($query, $update);   // Inserting Document        
        } catch(MongoCursorException $e) {

        }
        $manager->executeBulkWrite('dbName.mycol', $bulkWriteManager);  // Going to DB and Collection
    } catch (MongoDB\Driver\Exception\Exception $e) {
        $filename = basename(__FILE__);
        echo "The $filename script has experienced an error.\n"; 
        echo "It failed with the following exception:\n";       
        echo "Exception:", $e->getMessage(), "\n";
    }
?>

The problem in this code is that it successfully insert the data for the first time but when i update the data it does not update it.

Example: There is a document named as cars . Insert the data with object of year in one document. Let's say the Object is 2017, it contains color and car Model. As showing below; (Multiple objects with years. Year is unique in whole document.)

cars{
        2017{
            car=Motorolla
            color = blue
        }
        2016{
            car=Toyota
            color = green
        }
        2015{
            car=Corolla
            color = black
        }
    } 

If I want to update just make an object of 2017 like 2017{car=Updated-Motorolla color =Updated-blue} and insert in the document. It should update only the year 2017 object in side the document.

 cars{
            2017{
                car=Updated-Motorolla
                color =Updated-blue
            }
            2016{
                car=Toyota
                color = green
            }
            2015{
                car=Corolla
                color = black
            }
        } 
like image 394
Humty Avatar asked Feb 17 '17 13:02

Humty


Video Answer


1 Answers

You can try something like this. Its not possible to perform all the Mongo db operations just based off key as a value.

The first solution is written to stay close to OP's design.

Assuming you can add a key to the year.

{
  "cars": [{
      "year": "2017",
      "data": [{
          "car": "Motorolla",
          "color": "blue"
      }]
  }, {
      "year": "2016",
      "data": [{
          "car": "Toyota",
          "color": "green"
      }]
  }]
}

Makes it easy to reference the year by its value.

For example to add a new value into the data array for year 2017. You can try the below code.

Uses update positional $ operator.

query part to reference the array where 2017 record is stored.

update part using push to add the new car record to the existing data array for 2017 row.

<?php
    try {        
        $car = 'Malibu';
        $color = 'blue';
        $years = [2017];

        $manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
        $bulkWriteManager = new MongoDB\Driver\BulkWrite;

        //{"cars.year":2017}
        $query = ['cars.year' => $years[0]]; 

        //{ $push: { "cars.$.data": { "car":"chevy", "color":"black"} }}
        $update = ['$push'=> ['cars.$.data'=>['car' => $car, 'color' => $color]]];

        try {
            $bulkWriteManager->update($query, $update);  // Update Document
            echo 1;           
        } catch(MongoCursorException $e) {
            /* handle the exception */
            echo 0;
        }

        $manager->executeBulkWrite('dbName.carsCol', $bulkWriteManager);  // Going to DB and Collection

    } catch (MongoDB\Driver\Exception\Exception $e) {
        $filename = basename(__FILE__);
        echo "The $filename script has experienced an error.\n"; 
        echo "It failed with the following exception:\n";       
        echo "Exception:", $e->getMessage(), "\n";
    }

?>

For accessing data by year you can run below query.

Use query positional $operator to find the array index using the query part and reference that value in projection part.

db.collection.find({"cars.year":2017}, {"cars.$.data":1});

Alternative Solution :

This will take care of everything as just inserts

You are better off saving each car entry in its own document.

{ "year" : 2017, "car" : "Motorolla", "color" : "blue" }
{ "year" : 2016, "car" : "Toyota", "color" : "green" }
{ "year" : 2015, "car" : "Corolla", "color" : "black" }

For each entry you can use:

db.collection.insert({"year":2017,  "car":"Motorolla", "color":"blue"});

PHP Code:

 //{"car":"chevy", "color":"black", year: 2017}
 $insert = ['car' => $car, 'color' => $color, 'year' => $years[0]];

 try {
    $bulkWriteManager - > insert($insert); // Inserting Document
    echo 1;
 } catch (MongoCursorException $e) {
    /* handle the exception */
    echo 0;
 }

For access data by year you can use

db.collection.find({"year":2017});

Updated PHP code:

<?php 
try { 
  $cars = ['Motorolla','Toyota', 'Corolla'] ; 
  $colors = ['blue', 'green', 'black']; 

  $years = [2017, 2016, 2015]; 
  $manager = new MongoDB\Driver\Manager("mongodb://localhost:27017"); 
  $bulkWriteManager = new MongoDB\Driver\BulkWrite; 

  $query1 =["year" => $years[0]]; 
  $query2 =["year" => $years[1]]; 
  $query3 =["year" => $years[2]]; 

  $update1 = ['$set' => ['car' => $cars[0], 'color' => $colors[0]]]; 
  $update2 = ['$set' => ['car' => $cars[1], 'color' => $colors[1]]]; 
  $update3 = ['$set' => ['car' => $cars[2], 'color' => $colors[2]]]; 

  try { 
    $bulkWriteManager->update($query1, $update1, ["upsert" => true]); 
    $bulkWriteManager->update($query2, $update2, ["upsert" => true]); 
    $bulkWriteManager->update($query3, $update3, ["upsert" => true]); 
     echo 1; 
  } catch(MongoCursorException $e) { 
  /* handle the exception */ 
  echo 0; 
  } 

  $manager->executeBulkWrite('dbName.carsCol', $bulkWriteManager); // Going to DB and Collection 

  } catch (MongoDB\Driver\Exception\Exception $e) { 
    $filename = basename(__FILE__); 
    echo "The $filename script has experienced an error.\n"; 
    echo "It failed with the following exception:\n"; 
    echo "Exception:", $e->getMessage(), "\n"; 
  } 
?>

You can perform complex queries using aggregation pipeline and you can add index to make your response quicker.

Observations:

First Solution : Harder to update/insert data, but keeps everything together so easier to read data.

Second Solution : Cleaner and simpler to do CRUD operations on documents and use aggregation pipeline to preform complex queries.

like image 198
s7vr Avatar answered Oct 17 '22 11:10

s7vr