phemieny7
phemieny7

Reputation: 821

How to query an array in mongodb

Was trying to filter an array with another condition to query my MongoDB database

I have tried using the elemMatch to match exactly with the query, but it not working out.

Here is my code my shipment schema

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// Create Schema
const ShipmentSchema = new Schema({
  warehouseNo:{
    type: String,
    ref: 'users.unitNo'
  },
  packages:[
    {
        category:{
            type: String
        },
        quantity:{
            type: String
        },
        description:{
            type: String
        },
        trackingno:{
            type: String,
        },
        date:{
            type: Date,
            default: Date.now
        },
        length:{
            type: Number
        },
        width:{
            type: Number
        },
        height:{
            type: Number
        },
        weight:{
            type: Number
        },
        fee:{
            type: Number, 
        },
        status: {
            type: String,
            default: "In warehouse"
        },
  },
],

  shippingMode:{
    type: String,
  },

 date:{
        type: Date,
        default: Date.now
 }
});

module.exports = Shipments = mongoose.model('shipments', ShipmentSchema);

Here is my node js.

// @route   GET api/user/package
// @desc    Get all package
// @access  Private
router.get('/package', 
  passport.authenticate('jwt', { session: false }),

 (req, res) => {
  const errors = {};

  Shipments.findOne({warehouseNo : req.user.unitNo})
    .then(shipments => {
      if (shipments.packages.length === 0) {
        errors.nopackages = 'There are no packages for you yet';
        return res.status(404).json(errors);
      }
      res.json(shipments.packages);
    })
});

The code above bring every record in my mongoddb, but if i tried the below, where i ask it to fillter by package status. i got a code crash error

// @route   GET api/user/package
// @desc    Get all package
// @access  Private
router.get('/package', 
  passport.authenticate('jwt', { session: false }),

 (req, res) => {
  const errors = {};

  Shipments.find({warehouseNo : req.user.unitNo, "packages.status": "In warehouse"})
    .then(shipments => {
      if (shipments.packages.length === 0) {
        errors.nopackages = 'There are no packages for you yet';
        return res.status(404).json(errors);
      }
      res.json(shipments.packages);
    })
});

i expect to get something like this

{
    "status": "In warehouse",
    "date": "2019-09-11T10:19:02.834Z",
    "_id": "5d78ca160e47be29e13253b5",
    "category": "liquid",
    "quantity": "10 pieces",
    "description": "garri",
    "trackingno": "MHS085533395",
    "weight": 123,
    "length": 12,
    "height": 12,
    "width": 13
  }

instead i got this

[
  {
    "status": "Shipped",
    "date": "2019-09-11T10:17:46.485Z",
    "_id": "5d78c9ca0e47be29e13253b4",
    "category": "liquid",
    "quantity": "10 pieces",
    "description": "garri",
    "trackingno": "SDG561920753",
    "weight": 123,
    "height": 12,
    "width": 13
  },
  {
    "status": "In warehouse",
    "date": "2019-09-11T10:19:02.834Z",
    "_id": "5d78ca160e47be29e13253b5",
    "category": "liquid",
    "quantity": "10 pieces",
    "description": "garri",
    "trackingno": "MHS085533395",
    "weight": 123,
    "length": 12,
    "height": 12,
    "width": 13
  }
]

Upvotes: 0

Views: 61

Answers (2)

Rahul Beniwal
Rahul Beniwal

Reputation: 677

You defined warehouseNo as reference from other table. It must be some ID. Please make sure you are comparing the same

Upvotes: 0

Niraj Patel
Niraj Patel

Reputation: 810

You should use $elemMatch inside the key packages, i.e. db.getCollection('shipments').find( {warehouseNo: "123"}, { packages: { $elemMatch: { status: "In warehouse" }}}).

For Example: I have a collection as below:

{
"_id" : 1.0,
"name" : {
    "first" : "John",
    "last" : "Backus"
},
"birth" : ISODate("1924-12-03T05:00:00.000Z"),
"death" : ISODate("2007-03-17T04:00:00.000Z"),
"contribs" : [ 
    "Fortran", 
    "ALGOL", 
    "Backus-Naur Form", 
    "FP"
],
"awards" : [ 
    {
        "award" : "W.W. McDowell Award",
        "year" : 1967.0,
        "by" : "IEEE Computer Society"
    }, 
    {
        "award" : "National Medal of Science",
        "year" : 1975.0,
        "by" : "National Science Foundation"
    }, 
    {
        "award" : "Turing Award",
        "year" : 1977.0,
        "by" : "ACM"
    }, 
    {
        "award" : "Draper Prize",
        "year" : 1993.0,
        "by" : "National Academy of Engineering"
    }
]

}

Using query like this:

db.getCollection('bios').find( {_id: 1.0 }, { awards: { $elemMatch: { year: 1967.0 }}})

Gave me a result:

{ "_id" : 1.0, "awards" : [ { "award" : "W.W. McDowell Award", "year" : 1967.0, "by" : "IEEE Computer Society" } ] }

Hope this will help you.

Upvotes: 2

Related Questions