MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB :rechercher des valeurs de champ données dans un objet avec une clé inconnue

Bien que vous sembliez avoir approché cette structure en raison d'un problème avec les mises à jour lors de l'utilisation de tableaux imbriqués, vous n'avez en réalité causé qu'un autre problème en faisant autre chose qui n'est pas vraiment pris en charge, à savoir qu'il n'y a pas de "wildcard" concept de recherche de clés non spécifiées à l'aide des opérateurs de requête standard qui sont optimaux.

La seule façon de vraiment rechercher ces données est d'utiliser du code JavaScript sur le serveur pour parcourir les clés à l'aide de $where . Ce n'est clairement pas une très bonne idée car cela nécessite une force brute plutôt que d'utiliser des éléments utiles comme un index, mais cela peut être abordé comme suit :

db.theses.find(function() {
    var relations = this.relations;
    return Object.keys(relations).some(function(rel) {
        return relations[rel].type == "interpretation";
    });
))

Bien que cela renverra les objets de la collection qui contiennent la valeur imbriquée requise, il doit inspecter chaque objet de la collection afin de procéder à l'évaluation. C'est pourquoi une telle évaluation ne devrait vraiment être utilisée que lorsqu'elle est associée à quelque chose qui peut utiliser directement un index à la place comme valeur matérielle de l'objet de la collection.

Néanmoins, la meilleure solution consiste à envisager de remodeler les données pour tirer parti des index de recherche. Lorsqu'il est nécessaire de mettre à jour les informations "notations", puis essentiellement "aplatir" la structure pour considérer chaque élément "rating" comme les seules données du tableau à la place :

{
    "_id": "aeokejXMwGKvWzF5L",
    "text": "test",
    "relationsRatings": [
        {
            "relationId": "cF6iKAkDJg5eQGsgb",
            "type": "interpretation",
            "originId": "uFEjssN2RgcrgiTjh",
            "ratingId": 1,
            "ratingScore": 5
        },
        {
            "relationId": "cF6iKAkDJg5eQGsgb",
            "type": "interpretation",
            "originId": "uFEjssN2RgcrgiTjh",
            "ratingId": 2,
            "ratingScore": 6
        }
   ]
}

Maintenant, la recherche est bien sûr assez simple :

db.theses.find({ "relationsRatings.type": "interpretation" })

Et bien sûr le positionnel $ l'opérateur peut maintenant être utilisé avec la structure plus plate :

db.theses.update(
    { "relationsRatings.ratingId": 1 },
    { "$set": { "relationsRatings.$.ratingScore": 7 } }
)

Bien sûr, cela signifie la duplication des données "associées" pour chaque valeur "notes", mais c'est généralement le coût de la mise à jour par position correspondante car c'est tout ce qui est pris en charge avec un seul niveau d'imbrication de tableau uniquement.

Vous pouvez donc forcer la logique à correspondre à la façon dont vous l'avez structurée, mais ce n'est pas une bonne idée de le faire et cela entraînera des problèmes de performances. Si toutefois votre principal besoin ici est de mettre à jour les informations de "notation" plutôt que de simplement les ajouter à la liste interne, une structure plus plate sera plus avantageuse et bien sûr beaucoup plus rapide à rechercher.