Only query field if value has been passed from API in MongoDB - mongodb

I have created an API in Mule and have a number of queryParameters specified in the RAML file that I would like to use to query my store MongoDB collection.
A snippet of the collection looks like this:
{
"stores": [{
"storeId": 1234,
"storeName": "Shop Around Ltd",
"opens": "09:00:00.000Z",
"closes": "17:00:00.000Z",
"departments": ["clothing", "computers", "toys", "kitchen and home"],
"address": {
"street": "street1",
"city": "New York",
"state": "New York",
"zipCode": "10002"
}
}]
}
My problem is that the query parameters used to query the collection may be different each time so how can I write a dynamic query for MongoDB so it only queries on the fields that have been passed in with values instead of writing a query for each combination of query parameters? E.g. I may want to query based on zip code for one query so all the other fields will be blank and the next time I may want to query on the departments and whether the store will be open at 11am.
The query will be called from Mule.
Thanks

Related

Generate a JSON schema from an existing MongoDB collection

I have a MongoDB collection that contains a lot of documents. They are all roughly in the same format, though some of them are missing some properties while others are missing other properties. So for example:
[
{
"_id": "SKU14221",
"title": "Some Product",
"description": "Product Description",
"salesPrice": 19.99,
"specialPrice": 17.99,
"marketPrice": 22.99,
"puchasePrice": 12,
"currency": "USD",
"color": "red",
},
{
"_id": "SKU14222",
"title": "Another Product",
"description": "Product Description",
"salesPrice": 29.99,
"currency": "USD",
"size": "40",
}
]
I would like to automatically generate a schema from the collection. Ideally it would not which properties are present in all the documents and mark those as required. Detecting unique columns would also be nice, though not really all that necessary. In any event I would be modifying the schema after it's automatically generated.
I've noticed that there are tools that can do this for JSON. But short of downloading the entire collection as JSON, is it possible to do this using the MongoDb console or a CLI tool directly from the collection?
You could try this tool out. It appears to do exactly what you want.
Extract (and visualize) schema from Mongo database, including foreign
keys. Output is simple json file or html with dagre/d3.js diagram
(depending on command line options).
https://www.npmjs.com/package/extract-mongo-schema

MongoDB text search across two collections

I have an Order collection with address fields and User collection with names. The Order collection contains a string called userId, which is a "foreign key" into the users collection.
I am using an aggregation pipeline to filter, join, sort, and paginate queries. The problem is that I need to provide full text search on the address and name fields.
Because the $text match must be the first stage in a pipeline, I am not sure how to accomplish the goal of finding text matching any address or name field.
User collection
[{
"_id": "5cb8caa069fc1a4351cc3705",
"firstName": "James",
"lastName": "Bond"
},{
"_id": "5c58b8de8596d52c248f34d5",
"firstName": "Jack",
"lastName": "Ryan"
}]
Order Collection
[{
"_id": "5ccc94602e67ca44fe69f160",
"address": {
"streetAddress1": "1112 main st",
"streetAddress2": null,
"unitNumber": "unit 1112",
"city": "Jackson Hole",
"state": "WY",
"postalCode": "83001"
},
"userId": "5cb8caa069fc1a4351cc3705"
}]
A search for "Jack" should match both the name "Jack" and the city "Jackson Hole".

How to get documents from MongoDB based on greater or less than the given date

I need to get the record from MongoDB based on the date using MongoDB. I am providing my collection below.
f_task:
{
"_id": "5a13731f9402cc17f81ade10",
"taskname": "task1",
"description": "description",
"timestamp": "2017-11-21 05:58:14",
"created_by": "subhra",
"taskid": "858fca9e2e153a61515c0372e079c521",
"created_date": "21-11-2017"
}
Here I need to fetch record as per created_date. Suppose user input is 20-11-2017 or 22-11-2017 then I need query to get the record if the given date is greater than or less than the "created_date" value.

MongoDB - how to properly model relations

Let's assume we have the following collections:
Users
{
"id": MongoId,
"username": "jsloth",
"first_name": "John",
"last_name": "Sloth",
"display_name": "John Sloth"
}
Places
{
"id": MongoId,
"name": "Conference Room",
"description": "Some longer description of this place"
}
Meetings
{
"id": MongoId,
"name": "Very important meeting",
"place": <?>,
"timestamp": "1506493396",
"created_by": <?>
}
Later on, we want to return (e.g. from REST webservice) list of upcoming events like this:
[
{
"id": MongoId(Meetings),
"name": "Very important meeting",
"created_by": {
"id": MongoId(Users),
"display_name": "John Sloth",
},
"place": {
"id": MongoId(Places),
"name": "Conference Room",
}
},
...
]
It's important to return basic information that need to be displayed on the main page in web ui (so no additional calls are needed to render the table). That's why, each entry contains display_name of the user who created it and name of the place. I think that's a pretty common scenario.
Now my question is: how should I store this information in db (question mark values in Metting document)? I see 2 options:
1) Store references to other collections:
place: MongoId(Places)
(+) data is always consistent
(-) additional calls to db have to be made in order to construct the response
2) Denormalize data:
"place": {
"id": MongoId(Places),
"name": "Conference room",
}
(+) no need for additional calls (response can be constructed based on one document)
(-) data must be updated each time related documents are modified
What is the proper way of dealing with such scenario?
If I use option 1), how should I query other documents? Asking about each related document separately seems like an overkill. How about getting last 20 meetings, aggregate the list of related documents and then perform a query like db.users.find({_id: { $in: <id list> }})?
If I go for option 2), how should I keep the data in sync?
Thanks in advance for any advice!
You can keep the DB model you already have and still only do a single query as MongoDB introduced the $lookup aggregation in version 3.2. It is similar to join in RDBMS.
$lookup
Performs a left outer join to an unsharded collection in the same database to filter in documents from the “joined” collection for processing. The $lookup stage does an equality match between a field from the input documents with a field from the documents of the “joined” collection.
So instead of storing a reference to other collections, just store the document ID.

MongoDB manual reference

In MongoDB there is a nice tutorial on Manual Reference:
Example:
original_id = ObjectId()
db.places.insert({
"_id": original_id,
"name": "Broadway Center",
"url": "bc.example.net"
})
db.people.insert({
"name": "Erin",
"places_id": original_id,
"url": "bc.example.net/Erin"
})
Note, that this two documents are created at same time.
Question. I need to reference a Customer with an Order, therefore the Customer has been created long time before the Order, how can I add this reference of customer and insert in Order?
Wouldn't you need to do a findOne() on your customer first and add it's id property to your new document?