0

I have a collection that I would like to restrict duplicates of documents with specific fields. Following guidance at this SO thread, I have manually implemented an index:

{
  "playerName": 1,
  "comp.compName": 1,
  "comp.roundNo": 1
},
{
  "unique": true
}

Now when I try to insert a new document that would cause a duplicate, the PHP page / script errors with:

Fatal error: Uncaught MongoDB\Driver\Exception\BulkWriteException: E11000 duplicate key error collection: golf.round index: playerName_1_comp.name_1_comp.roundNo_1 dup key: { playerName: "Ernie Els", comp.name: "US Open 2021", comp.roundNo: 3 } in /usr/bin/vendor/mongodb/mongodb/src/Operation/InsertOne.php:134 Stack trace: #0 /usr/bin/vendor/mongodb/mongodb/src/Operation/InsertOne.php(134): MongoDB\Driver\Server->executeBulkWrite('golf.round', Object(MongoDB\Driver\BulkWrite), Array) #1 /usr/bin/vendor/mongodb/mongodb/src/Collection.php(931): MongoDB\Operation\InsertOne->execute(Object(MongoDB\Driver\Server)) #2 /var/www/html/selectComp.php(90): MongoDB\Collection->insertOne(Array) #3 {main} thrown in /usr/bin/vendor/mongodb/mongodb/src/Operation/InsertOne.php on line 134

To get all the data fields for the insert, I need to loop through the results of another comp collection query, with sub-query into round embedded objects. When fully complete, it should also require querying the selected player data too (likely a user login function, though trying to avoid it!):

$insertOneResult = $collectionRound->insertOne(
  [
    'playerName' => "Ernie Els", //$_COOKIE['playerName'],
    'playerId' => "a1b2c3", //$_COOKIE['playerId'],
    'date' => new MongoDB\BSON\UTCDateTime(strtotime("today")*1000),
    'comp' => [
      'id' => $comp['_id'],
      'name' => $comp['compName'],
      'tees' => $newScore['courseTee'],
      'roundNo' => $round['roundNo'],
      'scoringMethod' => $comp['compScoringMethod']
    ],
    'hcap' => 0, //$_COOKIE['playerHcap'],
    'holeCount' => 9, // from course or comp?
    'computedScore' => 0,
    'computedThru' => 0,
    'holes' => [],
    'team' => "PGA Tour", //$_COOKIE['playerTeam'],
    'countbackScores' => []
  ]
);

How do I handle this error? My intention was to simply restrict the adding of duplicates, and ignore this request. Based on usage, this might be notified to the user or simply ignored.

jingo_man
  • 509
  • 3
  • 13

1 Answers1

0

Why don't you use try catch exception handling while inserting the document. When there is a duplicate, it will throw you an error and you can catch the exception in the catch block and do nothing.

Try this:

try{
    $insertOneResult = $collectionRound->insertOne(
        [
        'playerName' => "Ernie Els", //$_COOKIE['playerName'],
        'playerId' => "a1b2c3", //$_COOKIE['playerId'],
        'date' => new MongoDB\BSON\UTCDateTime(strtotime("today")*1000),
        'comp' => [
            'id' => $comp['_id'],
            'name' => $comp['compName'],
            'tees' => $newScore['courseTee'],
            'roundNo' => $round['roundNo'],
            'scoringMethod' => $comp['compScoringMethod']
        ],
        'hcap' => 0, //$_COOKIE['playerHcap'],
        'holeCount' => 9, // from course or comp?
        'computedScore' => 0,
        'computedThru' => 0,
        'holes' => [],
        'team' => "PGA Tour", //$_COOKIE['playerTeam'],
        'countbackScores' => []
        ]
    );
}
catch(Exception $e){
    // This block will catch the duplicate exception
    // Dont do anything here, and just ignore the request
    echo 'Error message: ' .$e->getMessage();
}

Alternate : you can first try to find if the entry exists, using .find(), and if it exists, don't insert the document and ignore the request.

Ravi Shankar Bharti
  • 8,922
  • 5
  • 28
  • 52