Insert Array in existing Document

2019-03-04 16:08发布

问题:

I have a document like this:

_id: ObjectId("559c1d2ad8291bc9368b4568")
 tablename: "IWEO_IWBB"
 out_user: "pb"
 out_email: "email"
 out_date: "15.05.2015"

and want to add array like this:

"inventar": [
    {
        "ean": "2",
        "name": "name2",
        "runtime": "0",
        "art": "null",
        "marker": "null",
        "stammkost": "null",
        "accepted": "0"
    },
    {
        "ean": "1",
        "name": "name1",
        "runtime": "0",
        "art": "null",
        "marker": "null",
        "stammkost": "null",
        "accepted": "0"
    }
],

In my old PHP-Server I used the code below to insert it. The right command is "update". In node.js it seems to be another command.

foreach($jArray as $value){ 
    //$uuid = uniqid('', true);
    $tablename = $value['tablename'];
    $ean = $value["ean"];
    $runtime = $value["runtime"];
    $art = $value["art"];
    $marker = $value["marker"];
    $stammkost = $value["stammkost"];
    $new_data = array(
        //array (
        'ean' => $ean,
        'runtime' => $runtime,
        'art' => $art,
        'marker' => $marker,
        'stammkost' => $stammkost,
        'accepted' => '0'
        //)
    );
    try {
        $collection->update(array("tablename"=>$tablename),array('$push' => array("inventar" => $new_data)));
        echo json_encode($collection);
    }
    catch ( MongoConnectionException $e ) {
        echo '<p>Update failed</p>';
        exit();
    }           
}

In my new node.js I use the code below:

tables.forEach(function(table) {
var tablename = table.tablename;
var name = table.name ;
var ean = table.ean;
var runtime= table.runtime;
var art = table.art;
var marker = table.marker;
var stammkost = table.stammkost;
console.log(tablename+" "+ean+" "+name+" "+runtime+" "+art+" "+marker+" "+stammkost);
    OutAccept.update(function (err, data) {
    if (err) console.log(err);
    else {
    console.log(data);
    }
    });
    response.end();
    //}
    });

});

The output in console is:

IWEO_IWBB_01062015 1 name1 11337 A null null
{ ok: 0, n: 0, nModified: 0 }
IWEO_IWBB_01062015 2 name2 A null null
{ ok: 0, n: 0, nModified: 0 }

Why it isnt updated/inserted? Its the wrong command?

回答1:

There are a few things wrong in your code here. First and foremost to note is that you are running in an "async" environment now and you need to change the thinking on how you do some things.

Your previous PHP code is "blocking", which means that every line of code must complete before moving on to the next line of code. This includes waiting for a database server to perform an update and return the response.

You cannot use basic control loops with functions inside them that perform asynchronously. Instead you need something that can call the next iteration of the loop (or at least signal that a single iteration is complete ) once the asynchronous function "update" has actually returned a result.

The second point here is that "nothing updated" because you did not tell the function what to update or what to update the matched document with.

The following is analogous to you original PHP listing, but adjusted for "async" methods also use the async.eachSeries for the loop control from the async library:

async.eachSeries(
    tables,
    function(table,callback) {
        var tablename  = table.tablename;
        delete table.tablename;   // just remove the key rather than re-construct
        OutAccept.update(
            { "tablename": tablename },
            { "$push": { "inventar": table } },
            function(err,numAffected) {
                console.log( numAfftected ); // tells you how many are updated or nothing
                callback(err)
            }
        );
    },
    function(err) {
       // comes here on completion of all array items
    }
);

The .findOneAndUpdate() command instead returns the document that was modified and with the modifications only if you ask for them with { "new": true }

async.eachSeries(
    tables,
    function(table,callback) {
        var tablename  = table.tablename;
        delete table.tablename;
        OutAccept.findOneAndUpdate(
            { "tablename": tablename },
            { "$push": { "inventar": table } },
            { "new": true },
            function(err,doc) {
                console.log( doc ); // shows the modified document
                callback(err)
            }
        );
    },
    function(err) {
       // comes here on completion of all array items
    }
);

If you want to add Multiple array elements at once, or if you have even a single element directly in an array then use the $each modifier to $push:

var inventor =  [
    {
        "ean": "2",
        "name": "name2",
        "runtime": "0",
        "art": "null",
        "marker": "null",
        "stammkost": "null",
        "accepted": "0"
    },
    {
        "ean": "1",
        "name": "name1",
        "runtime": "0",
        "art": "null",
        "marker": "null",
        "stammkost": "null",
        "accepted": "0"
    }
];


OutAccept.update(
    { "tablename": tablename },
    { "$push": { "inventar": { "$each": inventar } } },
    function(err,numAffected) {
       // work in here
    }
);