6
votes

Upsert multiples enregistrements avec mongodb

J'essaie d'obtenir Mongodb à upérez plusieurs enregistrements avec la requête suivante, à l'aide de Mongomapper et du pilote Mongo Ruby.

{ "_id" : ObjectId("4d6babbac0d8bb8238d02099"), "event_id" : 1, "visit" : 2 }


1 commentaires

Pas exactement sûr de ce que le comportement prévu est. Est-ce "S'il y a un événement, augmente son visitent comptent, sinon créez un nouvel événement et définissez son visiter comptez sur 1"? Si oui, quel serait le event_id pour des événements nouvellement insérés?


3 Réponses :


2
votes

Ceci - correctement - n'entrera pas d'enregistrements avec event_id 1 ou 2 si elles n'existent pas déjà

db.fooo.update ({event_id: {$ in: [1,2]}}, {$ inc: {visitez: 1}}, true, true)

Ceci est parce que la partie objnew de la requête (voir http://www.mongodb.org/display/docs/updating#Updating-UpserSterSwithModificateurs ) n'a pas de valeur pour le champ event_id . En conséquence, vous aurez besoin d'au moins x + 1 voyages dans la base de données, où X est le nombre d'événements_ids, afin de vous assurer que vous insérez un enregistrement si on n'existe pas pour un événement particulier (le +1 vient de la requête ci-dessus. , qui augmente le compteur de visites pour les enregistrements existants). Pour le dire d'une manière différente, comment Mongodb sait-il que vous souhaitez utiliser la valeur 2 pour l'événement_id et non 1? Et pourquoi pas 6?

w.r.t. Insertion des lots avec Ruby, je pense qu'il est possible que le lien suivant suggère - bien que je n'ai utilisé que le pilote Java: Insertion / mise à jour par lots à l'aide de Mongoid?


1 commentaires

Pour clarifier, écrit pour la spécification BSON est en réalité "Batchable" par défaut. La plupart des pilotes prennent en charge une forme de mises à jour / inserts par lots, mais le Mongoïde n'est pas un pilote et peut ne pas prendre en charge toutes les fonctionnalités.



0
votes

Qu'est-ce que vous êtes après est le Rechercher et modifier la commande avec l'option upert défini sur true. Voir Exemple à partir de la suite de tests Mongo (même liée à dans le trouver et modifier docs) pour un exemple qui ressemble beaucoup à ce que vous décrivez dans votre question.


0 commentaires

-3
votes

J'ai trouvé un moyen de faire cela à l'aide de l'opérateur EVAL pour l'exécution du code côté serveur. Voici le code SNIPPIT:

def batchpush(body, item_opts = {})
    @batch << {
        :body => body,
        :duplicate_key => item_opts[:duplicate_key] || Mongo::Dequeue.generate_duplicate_key(body),
        :priority => item_opts[:priority] || @config[:default_priority]
    }
end

def batchprocess()
    js = %Q|
        function(batch) {
            var nowutc = new Date();
            var ret = [];
            for(i in batch){
                e = batch[i];
                //ret.push(e);
                var query = {
                    'duplicate_key': e.duplicate_key,
                    'complete': false,
                    'locked_at': null
                };
                var object = {
                    '$set': {
                        'body': e.body,
                        'inserted_at': nowutc,
                        'complete': false,
                        'locked_till': null,
                        'completed_at': null,
                        'priority': e.priority,
                        'duplicate_key': e.duplicate_key,
                        'completecount': 0
                    },
                    '$inc': {'count': 1}
                };

                db.#{collection.name}.update(query, object, true);
            }
            return ret;
        }
    |
    cmd = BSON::OrderedHash.new
    cmd['$eval'] = js
    cmd['args'] = [@batch]
    cmd['nolock'] = true
    result = collection.db.command(cmd)
    @batch.clear
    #pp result
end


0 commentaires