Search code examples
node.jsmongodbexpressmongoosemongoose-populate

Mongoose populate() not working as desired


I have a PaymentCard and a User schema, and want to define an existing user's ID when creating a new PaymentCard record to link that specific card to a specific customer. It does create the PaymentCard document with the customer's mongoID, however querying with .populate() does not return any cards on any of the users, and return empty arrays on all users.


Solution

  • To be able to populate cards from user, you need to push the card id to the user cards array when you create a payment. But I don't see that logic in your addPayment.

    Also, as already mentioned you need to correct your user schema, the ref must be "PaymentCard" for cards in the user schema. (And for the PaymentCard you need to correct ref for customer to the "Customer")

    To make things easy, I will exclude the jwt.verify parts, and describe my solution.

    As I already said, you need to save the created card id to the user's cards array:

    router.post("/addPayment", async (req, res) => {
      try {
        const result = await PaymentCard.create(req.body);
    
        const customerId = req.body.owner;
    
        const response = await Customer.findByIdAndUpdate(
          customerId,
          {
            $push: { cards: result._id } //result._id has the value of newly created card
          },
          { new: true }
        );
    
        res.send(response);
      } catch (err) {
        console.log(err);
        res.status(500).send("Something went wrong");
      }
    });
    

    Let's say you have this customer without any card:

    {
        "cards": [],
        "_id": "5e823f6f76322539e0fb1668",
        "name": "John",
        "surname": "Smith",
        "customerStatus": "Regular",
        "email": "[email protected]",
        "phoneNo": "123123123",
        "__v": 0
    }
    

    When we add a card with our post route, this customer will be like this:

    {
        "cards": [
            "5e82400776322539e0fb1669"
        ],
        "_id": "5e823f6f76322539e0fb1668",
        "name": "John",
        "surname": "Smith",
        "customerStatus": "Regular",
        "email": "[email protected]",
        "phoneNo": "123123123",
        "__v": 0
    }
    

    The added card document was:

    {
        "owner": "5e823f6f76322539e0fb1668",
        "nameOnCard": "John Smith",
        "cardNumber":"1234123412341234",
        "cardIssuer": "VISA",
        "cvc": 123,
        "exp": 202008
    }
    

    Now you can populate the user's cards like this:

    router.get("/getAll", async (req, res) => {
      try {
        const customerId = "5e823f6f76322539e0fb1668";
    
        const result = await Customer.findById(customerId).populate("cards");
    
        res.send(result);
      } catch (err) {
        console.log(err);
        res.status(500).send("Something went wrong");
      }
    });
    

    This will give you the following result:

    {
        "cards": [
            {
                "_id": "5e82400776322539e0fb1669",
                "owner": "5e823f6f76322539e0fb1668",
                "nameOnCard": "John Smith",
                "cardNumber": "1234123412341234",
                "cardIssuer": "VISA",
                "cvc": 123,
                "exp": 202008,
                "__v": 0
            }
        ],
        "_id": "5e823f6f76322539e0fb1668",
        "name": "John",
        "surname": "Smith",
        "customerStatus": "Regular",
        "email": "[email protected]",
        "phoneNo": "123123123",
        "__v": 0
    }