JOHN
JOHN

Reputation: 1511

How to query nested documents in MongoDB?

I am very new to database and MongoDB. I tried to stored financial statment information in the database with each document representing a company.

I have created a nested documents (maybe not a good way), like the following diagram. the outest level contains Annual statement, Basic info, Key Map, and Interim Statement. And within Annual statement, there are different dates. And within dates, we have different types of statements (INC, BAL, CAS), and then the inner level contains the real data. enter image description here

My question is how can I query the db to give me all documents contain 2017 statements (for example)?

The year is now formated as YYYY-MM_DD. but I only wants to filter YYYY.

Upvotes: 0

Views: 301

Answers (2)

matthPen
matthPen

Reputation: 4343

I highly discourage to use variable (date, INC here) as field name. It will be (much more) harded to query, update, you cannot use index. So it's a very bad idea in most of case, even if it can be 'acceptable' (but bad practice) in case of a few numbers of static values (INC, BAL, CAS).

My advice will be to change your schema for something easier to use like for example :

[
  {
    "annual_statement": [
        { "date": ISODate("2017-12-31"),
          "INC":{
              "SREV": 1322.5,
              "RTLR": 1423.4,
              ...
            },
          "BAL":{...},
          "CAS":{...}
        },
      {   "date": ISODate("2017-12-31"),
          "INC":{
              "SREV": 1322.5,
              "RTLR": 1423.4,
              ...
            },
          "BAL":{...},
          "CAS":{...}
        }
    ]
  }
]

To query this schema, use the following :

db.collection.find({
  "annual_statement": {
    $elemMatch: {
      date: {
        $lt: ISODate("2018-01-01"),
        $gte: ISODate("2017-01-01"),

      }
    }
  }
})

Will return you whole documents where at least on date is in 2017.

Adding projection like following will return you only matching annual statements :

db.collection.find({
  "annual_statement": {
    $elemMatch: {
      date: {
        $lt: ISODate("2018-01-01"),
        $gte: ISODate("2017-01-01"),

      }
    }
  }
},
{
  "annual_statement": {
    $elemMatch: {
      date: {
        $lt: ISODate("2018-01-01"),
        $gte: ISODate("2017-01-01"),

      }
    }
  }
})

Upvotes: 1

chuck_sum
chuck_sum

Reputation: 111

Use $exists (note I'm using python - pymongo driver syntax below - yours may differ) https://docs.mongodb.com/manual/reference/operator/query/exists/

Example: Find all "2017" "INC" records, by company.

year_exists=db.collection.find({'Annual.2017-12-31': {'$exists':True}})

for business in year_exists:
     bus_name = business['BasicInfo']['CompanyName']
     financials_INC = business['Annual']['2017-12-31']['INC'])
     print(bus_name, financials_INC)

Upvotes: 0

Related Questions