J'ai une collection MongoDB avec certains documents qui ont un champ appelé Personal.FirstName et un autre champ appelé Personal.Surname. Certains documents sont en désordre et ont le prénom et le nom de la personne dans les deux champs. Par exemple, certains documents ont Personal.FirstName = 'John Doe' et Personal.Surname = 'John Doe'.

Je veux écrire une déclaration de mise à jour mongo qui fera ce qui suit:

  • Trouvez tous les documents qui ont une section personnelle
  • Trouvez tous les documents où Personal.FirstName == Personal.Surname
  • Mettez à jour Personal.FirstName pour qu'il ne soit que la première partie de Personal.FirstName avant l'espace
  • Mettez à jour Personal.Surname pour qu'il ne soit que la deuxième partie de Personal.Surname après l'espace

Est-ce possible dans une déclaration de mise à jour mongo? Je suis nouveau sur Mongo et je sais très peu comment l'interroger.

EDIT: voici un exemple de document

{
    "_id" : LUUID("fcd140b1-ec0f-0c49-aa79-fed00899290e"),
    "Personal" : {
        "FirstName" : "John Doe",
        "Surname" : "John Doe"
    }
}
1
Corey Burnett 16 janv. 2017 à 20:44

2 réponses

Meilleure réponse

Vous ne pouvez pas faire cela en une seule requête, mais vous pouvez y parvenir en itérant sur le résultat comme ceci:

db.name.find({$and: [{Personal: {$exists: true}}, {$where: "this.Personal.FirstName == this.Personal.Surname"}]}).forEach(function(e,i){
    var parts = e.Personal.FirstName.split(" ");
    e.Personal.FirstName = parts[0];
    e.Personal.Surname = parts[1];
    db.name.save(e); 
})

Résultat:

{ "_id" : "fcd140b1-ec0f-0c49-aa79-fed00899290e", "Personal" : { "FirstName" : "John", "Surname" : "Doe" } }
2
felix 16 janv. 2017 à 18:25

L'idée est d'obtenir un sous-ensemble des documents de votre collection en filtrant les documents qui correspondent aux critères spécifiés. Une fois que vous obtenez le sous-ensemble, vous parcourez la liste et mettez à jour chaque document dans une boucle.

Maintenant, pour obtenir le sous-ensemble, vous devez exécuter un pipeline d'agrégation qui est plus rapide que de faire un filtre en utilisant find() et $where opérateur. Prenons l'exemple suivant {{ Opération X2}} qui utilise $redact comme mécanisme de filtrage puis un $project pour créer un champ supplémentaire que vous pouvez utiliser dans votre mise à jour. Le curseur de {{ La méthode X5}} contenant les résultats peut ensuite être itérée avec sa forEach() et ensuite mettre à jour la collection sur les documents du sous-ensemble:

db.collection.aggregate([
    {
        "$redact": {
            "$cond": [
                {
                    "$and": [
                        { "$eq": [ "$Personal.FirstName", "$Personal.Surname" ] },
                        {
                            "$gt": [
                                {
                                    "$size": {
                                        "$split": ["$Personal.FirstName", " "]
                                    }
                                },
                                0
                            ]
                        }
                    ]
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    },
    {
        "$project": {
            "FirstName": {
                "$arrayElemAt": [
                    { "$split": ["$Personal.FirstName", " "] },
                    0
                ]
            },
            "Surname": {
                "$arrayElemAt": [
                    { "$split": ["$Personal.FirstName", " "] },
                    1
                ]
            }
        }
    }
]).forEach(function(doc) {
    db.collection.updateOne(
        { "_id": doc._id },
        {
            "$set": {
                "Personal.FirstName": doc.FirstName,
                "Personal.Surname": doc.Surname,
            }
        }
    )
})

Utilisation du cadre d'agrégation avec {{X0} } L'opérateur de pipeline vous permet de traiter la condition logique avec le $cond et utilise les opérations spéciales $$KEEP pour" conserver "le document où la condition logique est vraie ou $$PRUNE pour" supprimer "le document où se trouvait la condition faux.

Cela devrait améliorer considérablement les performances car le {{ L'opérateur X0}} utilise les opérateurs natifs de MongoDB lors d'une opération de requête avec $where appelle le moteur JavaScript pour évaluer le code Javascript sur chaque document et vérifie la condition pour chacun, donc peut être très lent car MongoDB évalue non- Requête $where opérations avant $where expressions et non- $where peuvent utiliser un index.

0
chridam 16 janv. 2017 à 19:41