GET a string inside a object nested within a array - mongodb

I have a get router that gets orders with the time stamp
router.get('/api/order/:date/:time', function (req,res,next) {
Box.find({orders: {date:req.params.date}}.then (function (order){
console.log('GET ORDER / with ', req.params.date);
res.send(order);
}).catch(next);
});
the :time is just to allow my frontend to call this specific get which offers a timestamp inside the :date parameter
now, the model
const orderSchema = new Schema({
name : { type : String },
date : { type : String }, // date stamp of only YYYY/MM/DD
orders : { type : Array}
});
Inside this array of orders you can find elements such as:
"orders" : [
{
"type" : "Meat Lover Slice",
"extraType" : "na",
"extraInfo" : "na",
"date" : "2018-09-27:08:47:07",
"quantity" : "1",
"size" : "medium",
"crust" : "normal",
"split" : false,
and so on.. (15 or so elements)
You can see inside this array of orders, there are time stamped with YYYY/MM/DD:HH:MM:SS (2018-09-27:08:47:07).
inside the router, I do get
console.log('GET ORDER / with ', req.params.date) // > GET ORDER / with 2018-09-27:08:47:07
so it does receive the time at this route.
But with the params, how do I filter out the the specific orders matching that element?

If I have understood the question correctly is the short answer is that you can't, there is no way to "filter" sub-documents in a standard query. (Have a look at Return only matched sub-document elements within a nested array for a more in depth answer.)
What you could do is either use MongoDB Aggregations (https://docs.mongodb.com/manual/aggregation/) or do the filtering yourself when you have received the query result.
I would suggest doing the filtering yourself.

Related

Creating a variable in nested mongodb document

_id : { name : xyz,
Rollnumber : 123}
Stats : [ { subject : Maths,
Examdate : 2020-08-24 },
{ Subject : English,
Examdate : 2020-08-24} ]
I've a mongodb document like this :
To extract the name and roll number in a variable I can do like:
Var a = _id.name;
Var b = _id.rollnumber;
I want to extract the Examdate field in a variable , they can be multiples within one document.
Var c = Stats.Examdate;
It's returning unknown type error,
I've to use these three variables in a cursor, is there any way to achieve it .

Getting distinct values from object array MongoDB

{
"_id" : NUUID("f5050a5d-b3be-4de6-a135-a119436fb511"),
"CoursesData" : [
{
"Name" : "Naturgræs",
"Value" : 1
}
],
"FacilityType" : {
"_id" : NUUID("a1b4844b-518b-40e2-8aa5-8ee399ac2d4e")
}
}
I want to retrieve a list with the distinct values from the field Name inside my object array of CourseData. Filtered by FacilityType._id. I tried using both $facet and the distinct operator, but it doesn't seems to like object arrays.
My result should look like this (or similar):
FacilityType (a1b4844b-518b-40e2-8aa5-8ee399ac2d4e),
CourseData: [Name1, Name2, Name3]
Update
From the answer given below, this is how you do it with the C# driver, if anyone needs to do the same.
FieldDefinition<FacilityDocument, string> field = "CoursesData.Name";
var result = FacilityCollection.Distinct(field, Builders<FacilityDocument>.Filter.Eq(x => x.FacilityType.ID, new Guid("a1b4844b-518b-40e2-8aa5-8ee399ac2d4e"))).ToList();
You can use distinct(). It will return distinct element for a specific field from document which match a query
For example if you want distinct value of Name field for facility "a1b4844b-518b-40e2-8aa5-8ee399ac2d4e", run this query:
db.collection.distinct("CoursesData.Name", {"FacilityType._id": "a1b4844b-518b-40e2-8aa5-8ee39ac2d4e"})
it will return :
[ "Naturgræs", ... ]

Searching with dynamic field name in MongoDB

I have a situation where records in Mongo DB are like :
{
"_id" : "xxxx",
"_class" : "xxxx",
"orgId" : xxx,
"targetKeyToOrgIdMap" : {
"46784_56139542ecaa34c13ba9e314" : 46784,
"47530_562f1bc5fc1c1831d38d1900" : 47530,
"700004280_56c18369fc1cde1e2a017afc" : 700004280
},
}
I have to find out the records where child nodes of targetKeyToOrgIdMap has a particular set of values. That means, I know what the value is going to be there in the record in "46784_56139542ecaa34c13ba9e314" : 46784 part. And the field name is variable, its combination of the value and some random string.
In above example, I have 46784, and I need to find all the records which have 46784 in that respective field.
Is there any way I can fire some regex or something like that or by using any other mean where I would get the records which has the value I need in the child nodes of the field targetKeyToOrgIdMap.
Thanks in advance
You could use MongoDB's $where like this:
db.myCollection.find( { $where: function() {
for (var key in obj.targetKeyToOrgIdMap) {
if (obj.targetKeyToOrgIdMap[key] == 46784){
return true;
}
}
}}).each { obj ->
println obj
}
But be aware that this will require a full table scan where the function is executed for each document. See documentation.

How to insert in a collection when other collections already exists

I am very new to noSQL databases. I have started my journey with mongodb Database in noSQL. Upto today I used mySQL and MS SQL Server. I know how to create tables and relationships between them. But this noSQL concept is totally different than that. So, I am asking this question. I hope I will learn sooner to work with noSQL databases.
I have used the following queries in mongodb to create collections and insert data in it:
db.createCollection('Parties');
db.parties.insert({partyName:"Best Sellers", mobileNo:"9876543214"});
db.parties.insert({partyName:"National Traders", mobileNo:"9876543215"});
db.createCollection('items');
db.items.insert({itemName:"Item-A", size:"12"});
db.items.insert({itemName:"Item-B", size:"8"});
db.createCollection('orders');
Visually my order will have these fields:
Order No : AB/123
Date of Order: 17-06-2016
Party Name : National Traders // It will be a select
Item Name Quantity Rate Amount
--------------------------------------------------------
Item-A //Select 200 20 4000
Item-B //Select 100 30 3000
--------------------------------------------------------
300 7000
My question is:
How can I make a query for mongodb to insert in order collection? I have never used something like nested collections. Can anybosy give me an example??
Update:
Here is the diagram of my database in relational database :
How can I convert it to mongodb style??
Update2:
I have tried to add this code for model order in Node.js:
var mongoose = require('mongoose');
var orderSchema = new mongoose.Schema({
salesOrderId: String,
orderDate: Date,
party: {type: Schema.Types.ObjectId, ref:'Party'},
items:[{{type: Schema.Types.ObjectId, ref:'Item'}, quantity: Number, rate: Number}],
dispatches:{
invoiceId: Number,
dispatchDate: Date,
items: [{{type: Schema.Types.ObjectId, ref:'Item'}, quantity: Number, rate: Number}]
}
});
mongoose.model('Order', orderSchema);
MongoDB doesn't follow the relational database data structure.
Copying the SQL data structure to MongoDB is not the ideal way of using MongoDB. Your application should be modified to work with MongoDB style of data structure.
For storing order data, I would suggest using just one collection which has the entire order data.
{
orderNumber : 7283,
party : {partyName:"Best Sellers", mobileNo:"9876543214"},
items : [
{itemName:"Item-A", size:"12"},
{itemName:"Item-B", size:"8"},
.....
]
orderDate : <>,
total : <>,
status : <>,
.....
}
this problem need three collections:
Item - which will hold item data
Party - which will hold party data
Order which will hold all related data
When order is placed by party, in order collection we are creating document and placing in it some subdocuments:
Order data (id, date, etc)
PartyDetails - as a whole document from party collection
Items - contains an array of all items selected by party with details (Quantity, Rate,etc)
Dispatch and DispatchDetails - those depend of how items are shipped
this structure utilities efficiently document oriented storage, and every time you need to check order status, you need just to ask for one document and you will get subdocuments at one go.
To insert data in such collection will depend of application language you will use, but I think this answer will provide you with power of document database solution.
Any comments welcome!
* EDIT *
var itemToInsertA = db.items.find({"itemName" : "Item-A"}).toArray()
var itemToInsertB = db.items.find({"itemName" : "Item-B"}).toArray()
var party = db.parties.find({"partyName" : "National Traders"}).toArray()
var order = {
//_id - will be assigned by db - but we can do it mannually
orderDate : new Date(), // now
salesOrderId : "Need to provide this from sale now or later",
PartyDetails : party[0],
Items : [{
item : itemToInsertA[0],
Quantity : 200,
Rate : 20,
ValueAtTransactionDate : 4000
}, {
item : itemToInsertB[0],
Quantity : 100,
Rate : 30,
ValueAtTransactionDate : 3000
}
]
}
db.orders.insertOne(order)
so finnaly our order looks like this:
{
"_id" : ObjectId("5767d030ecf8248c30af068c"),
"orderDate" : ISODate("2016-06-20T11:14:56.372Z"),
"salesOrderId" : "Need to provide this from sale now or later",
"PartyDetails" : {
"_id" : ObjectId("5767ce26ecf8248c30af0686"),
"partyName" : "National Traders",
"mobileNo" : "9876543215"
},
"Items" : [
{
"item" : {
"_id" : ObjectId("5767ce26ecf8248c30af0687"),
"itemName" : "Item-A",
"size" : "12"
},
"Quantity" : 200.0,
"Rate" : 20.0,
"ValueAtTransactionDate" : 4000.0
},
{
"item" : {
"_id" : ObjectId("5767ce26ecf8248c30af0688"),
"itemName" : "Item-B",
"size" : "8"
},
"Quantity" : 100.0,
"Rate" : 30.0,
"ValueAtTransactionDate" : 3000.0
}
]
}
to create a diagram I used plantUML with QEditor.
plantumpl dump
#startuml
package "Party"{
[PartyId]
[PartyCode]
[PartyName]
[MobileNumber]
}
package "Item"{
[ItemId]
[ItemCode]
[ItemName]
}
package "Order"{
[OrderId]
[SalesOrderId]
[OrderDate]
node "Dispatch"{
[InvoiceId]
[SalesInvoiceId]
[DateOfDispatch]
}
node "DispatchItemTransaction"{
[DispatchItemTId]
[Quantity.]
[Rate.]
[ItemId.]
[InvoiceId.]
}
component PartyDetails
node "Items"{
component ItemDetails
[Quantity]
[Rate]
[Value]
}
}
Item -> ItemDetails
ItemDetails-->ItemId.
Party -down-> PartyDetails
#enduml

Mongo db : query on nested json

Sample json object :
{ "_id" : ObjectId( "55887982498e2bef5a5f96db" ),
"a" : "x",
"q" : "null",
"p" : "",
"s" : "{\"f\":{\"b\":[\"I\"]},\"time\":\"fs\"}" }
need all documents where time = fs
My query :
{"s":{"time" : "fs"}}
above returns zero products but that is not true.
There are two problems here. First of all s is clearly a string so your query cannot work. You can use $regex as below but it won't be very efficient:
{s: {$regex: '"time"\:"fs"'}}
I would suggest converting s fields to proper documents. You can use JSON.parse to do it. Documents can be updated based on a current value using db.foo.find().snapshot().forEach. See this answer for details.
Second problem is your query is simply wrong. To match time field you should use dot notation:
{"s.time" : "fs"})