MongoDB/PHP removing a specific array item inside

2019-06-11 03:19发布

问题:

Now, I have a document in my collection that I would like to delete on click, and those are comments inside the post document.

Here's the structure:

{
    "_id" : "design-patterns-vs-frameworks",
    "title" : "Design Patterns vs Frameworks",
    "category" : [ 
        "Frameworks", 
        " Design Patterns", 
        " PHP"
    ],
    "date_time" : ISODate("2014-09-02T13:45:29.124Z"),
    "description" : "Frameworks vs Design Patterns",
    "content" : " Content!",
    "author" : "Maciej Sitko",
    "comments" : [ 
        {
            "_id" : ObjectId("54061528af105b51133c986c"),
            "comment" : "ashfklsfsl\r\n",
            "author" : "maciejsitko",
            "date" : ISODate("2014-09-02T19:06:16.646Z")
        }, 
        {
            "_id" : ObjectId("5406152caf105b51133c986d"),
            "comment" : "lfasdlfsfl",
            "author" : "maciejsitko",
            "date" : ISODate("2014-09-02T19:06:20.652Z")
        }
    ]
}

The full delete link is:

delete.php?post=css-clearfix-explained&id=540617e3af105b8d133c986a (as you see two get variables 'post' and 'id')

I tried several solutions,

-First one:

$collection->update( array("_id" => $_GET['post']), array( '$unset' => 
 array("comments" => array("_id" => $_GET['id']))) );

This one just removed all of my comments inside the comments array.

-Second:

$delete = array('$pull' => array("comments" => array( '_id' => $_GET['id'])));
$collection->update(array('_id' => $_GET['post']), $delete);

Did not pretty much do anything, strangely enough, this should work, right?

-Third solution:

$collection->remove( array('_id' => $_GET['post'], 'comments._id' => $_GET['id']));

What would be the proper way of achieving this? I struggled on this one a lot, even implementing some aggregation query and it didn't work out.

回答1:

To remove an element from an array you use the $pull operator. This takes a "query" expression to identify the element you wish to remove:

$collection->update( 
    array("_id" => $_GET['post']),
    array( '$pull' => 
        array(
            "comments" => array(
                "_id" => new MongoId( $_GET['id'] )
            )
        )
    )
);

The "query" portion of $pull acts on the individual elements of the array specified, so anything matching the condition will be removed from the array. But also importantly your request parameter is a "string" so you need to cast this as an actual ObjectId value which you can cast in PHP with the MongoId class from the driver.

NOTE Modern driver releases use MongoDB\BSON\ObjectId as the correct method for casting "string hex value" into an actual ObjectId representation.