2
votes

Comment interroger par champ de référence dans mongodb?

J'ai 2 schémas mongo:

Utilisateur:

SELECT * 
FROM User
JOIN Country 
ON User.country = Country._id 
WHERE Country.name = VietNam

Pays:

{
  _id: ObjectId,
  name: String
}

Je veux obtenir tous les utilisateurs ont le nom de pays est VietNam.

Quelle est la requête (requête uniquement à l'utilisateur) que je peux utiliser dans ce cas ??

Je veux ressembler à cette requête SQL: p >

{
  _id: ObjectId,
  name: String,
  country: ObjectId // Reference to schema Country
}


0 commentaires

4 Réponses :


1
votes

Contrairement aux bases de données relationnelles, ce n'est pas quelque chose dans lequel Mongo est doué, et vous devez généralement structurer vos schémas d'une manière différente lorsque vous utilisez NoSQL. Dans ce cas, vous pouvez ajouter un champ countryName à la collection user (et peut-être un index sur le pays) afin de pouvoir interroger {countryName: "Vietnam" } . (Au lieu de country-name, il serait probablement plus judicieux d'utiliser le code de pays iso-2)

Si vous devez effectuer une "jointure", vous pouvez utiliser Opérateur $ lookup dans le pipeline d'agrégation - gardez simplement à l'esprit que les agrégations ne s'adaptent pas bien et ont tendance à être un peu difficiles à écrire.


4 commentaires

Donc, lorsque je mets à jour le nom du pays de countryId A. Je dois trouver tous les enregistrements d'utilisateur dont le countryId est A et mettre à jour tous ces enregistrements ?? C'est bon pour la performance


À quelle fréquence les noms de pays (ou codes de pays ISO-2) changent-ils? La mise à jour de toutes les entités utilisateur est une opération très coûteuse, mais c'est une opération qui ne se produira que rarement (et peut être évitée en demandant au code côté application de renommer). Avoir une recherche supplémentaire avec chaque requête finira par coûter beaucoup plus cher.


Mais avec les enregistrements généralement à changer?


En général, vous voudrez dénormaliser vos données dans mongo et une partie de ce travail consiste souvent à vous assurer que plusieurs documents restent synchronisés. Si les enregistrements changent souvent, l'utilisation de $ lookup peut vous permettre de renvoyer des documents de différentes collections. La manière de structurer vos données et vos requêtes dépend fortement de votre cas d'utilisation



0
votes

Voici le code que j'utilise généralement:

Models / users.js

const express = require("express");
const router = express.Router();
const Users = require("../models/users");

router.post("/register", async(req, res) => {
    try{
      const Me = await Users.create({name: req.body.name, country: req.body.country})
      /* If you make the request correctly on the frontend req.body.name is a 
         string and req.body.country is an object with one property, it's name */
      res.status(200).json({
          data: Me
      });
    }
    catch(err){
      res.status(400).json({message:err.message})


controllers / users.js

const mongoose = require("mongoose");
const Countries = require("./countries");

const UsersSchema = new mongoose.Schema({
    name: Sting,
    country: Countries.schema
});

module.exports = mongoose.model("Users", UsersSchema);

Puisque le sous-schéma est un objet, vous le référencez comme Me.country.name. J'espère que cela vous aidera!


2 commentaires

Merci. Mais je veux garder 2 schémas et l'utilisateur ne stocke que l'ID du pays, pas l'objet du pays. Étant donné que la collection de pays sera utilisée pour afficher les pays de la liste, elle doit être séparée en 2 schémas. Et le problème principal est que je ne sais pas comment interroger l'utilisateur par nom de pays


vous auriez toujours 2 collections de documents mais si vous voulez appeler l'utilisateur par le pays, vous faites Users.findMany ({country: req.body.country}) . Je suppose que j'ai mal lu votre question, mais ceci est une excellente référence à toutes choses MongoDB.



2
votes

Vous pouvez utiliser l'agrégation ci-dessous avec mongodb 3.6 et supérieur

db.country.aggregate([
  { "$match": { "name": "VietNam" } },
  { "$lookup": {
    "from": Users.collection.name,
    "let": { "countryId": "$_id" },
    "pipeline": [
      { "$match": { "$expr": { "$eq": [ "$country", "$$countryId" ] } } },
    ],
    "as": "users",
  }},
  { "$unwind": "$users" },
  { "$replaceRoot": { "newRoot": "$users" }}
])


1 commentaires

Merci. Cela a très bien fonctionné. Mais puis-je combiner des conditions comme user.name = 'Anthony' et country.name = 'Vietnam'?



0
votes

si vous souhaitez associer 2 collections ou plus, vous devez définir l'objet de référence de la collection

ma solution, veuillez vérifier cette https://mongoosejs.com/docs/populate.html


0 commentaires