N1QL to get org Id of the employee with id 2 in both the org doc - n1ql

"orgId": 1,
"orgName":"orgOne"
"empList": [
{
"empId": 1,
"empName":"emp1"
},
{
"empId": 2,
"empName":"emp2"
},
{
"empId": 3,
"empName":"emp3"
}
]
},
{
"orgId": 2,
"orgName":"orgTwo"
"empList": [
{
"empId": 2,
"empName":"emp2"
},{
"empId": 3,
"empName":"emp3"
}
]
}

The following query gives orgId for empId =2
SELECT d.orgId
FROM default AS d
WHERE ANY e IN d.empList SATISFIES e.empId = 2 END;
If you are looking different could you explain more details.

Related

Mongoose updateMany dynamically

I have a collection which looks like this (fields removed for brevity):
[
{ "id": "A", "name": "AA" ,"arrayField": [1, 2, 3] },
{ "id": "B", "name": "BB" ,"arrayField": [4, 5, 6] },
{ "id": "C", "name": "CC" ,"arrayField": [7, 8] }
]
Consider each object as a document.
Now in my application, after some business logic, I have an array of POJOs which look like this:
[
{ "id": "A", "name": "AB", "arrayField": [1, 2, 3] },
{ "id": "B", "name": "VB", "arrayField": [4, 5, 6] },
{ "id": "C", "name": "DE", "arrayField": [7, 8] }
{ "id": "D", "name": "GG", "arrayField": [10, 11] }
]
Note that these objects don't have the other fields required by the document.
How can I update the MongoDB collection to reflect the same as in the array of objects?
I would like to update only the arrayField and the name fields of documents with id A, B** and C to reflect the array of objects.
There is also a new document with id D which have to be inserted in the collection (the other fields will be taken care of as they have default values in the schema).
Things I've tried/thought of
Note: arr is the array of objects being talked about.
updateMany with upsert:
Model.updateMany({ id: { $in: arr.map(({ id }) => id) } }, arr, { upsert: true });
Mapping over the array of objects and updating with upsert:
await Promise.all(
arr.map(({ id, arrayField, name }) => {
return Model.updateOne({ id }, { $set: { arrayField, name } }, { upsert: true });
})
);
Is there any way to do this using transactions/aggregations/etc.?
As #ray suggested in the comments, I was looking for bulk operations. I did something along the lines of:
const bulk = Model.initializeUnorderdBulkOp();
arr.forEach(({ id, arrayField, name }) => {
bulk.find({ id }).upsert().updateOne({ $set: { arrayField, name } });
});
bulk.execute();

Increment value if provide date is date of array in Mongodb using NodeJS

I want to decrement slotsAvailable by 1 and increment slotsBooked by 1 if provide courtId is equal to courtId which in slotTracker and provided date is there in dates array
Sample Data
{
"slotTracker" : [
{
"courtID" : 1,
"dates" : [
{
"date": "2021-03-17T08:03:02.197Z",
"slotsBooked": 0,
"slotsAvailable": 10
},
{
"date": "2021-04-17T08:03:02.197Z",
"slotsBooked": 0,
"slotsAvailable": 15
},
]
},
{
"courtID" : 2,
"dates" : [
{
"date": "2021-03-17T08:03:02.197Z",
"slotsBooked": 0,
"slotsAvailable": 15
},
{
"date": "2021-04-17T08:03:02.197Z",
"slotsBooked": 0, //increase this by 1
"slotsAvailable": 5 //decrease this by 1
},
]
}
]
}
for example: provided courtId is 1 and provided date is "2021-03-17T08:03:02.197Z". so it will change the slotAvailable couter
{
"courtID" : 2,
"dates":[{
"date": "2021-04-17T08:03:02.197Z",
"slotsBooked": 1, //increase this by 1
"slotsAvailable": 4 //decrease this by 1
},
{
"date": "2021-03-17T08:03:02.197Z",
"slotsBooked": 0,
"slotsAvailable": 15
},
]
}
db.sample.update({
courtID: 2,
"dates.date" : "2021-04-17T08:03:02.197Z"
} ,
{$inc : {
"dates.$.slotsBooked" : 1, "dates.$.slotsAvailable" : -1}
});
Please try this out :)

How to filter this array of object in Node.js?

I have some data which looks like this-
[
{
"element": 1,
"id": 1
},
{
"element": 1,
"id": 2
},
{
"element": 2,
"id": 1
},
{
"element": 2,
"id": 2
},
{
"element": 3,
"id": 1
}
]
I have data as above as it is array of object and I want to filter as given below mainly in Node.js where I want to filter with element and return new array. It will be helpful if I get any solution for this.
[
{
"element": 1,
"data": [
{
"element": 1,
"id": 1
},
{
"element": 1,
"id": 2
}
]
},
{
"element": 2,
"data": [
{
"element": 2,
"id": 1
}
]
},
{
"element": 3,
"data": [
{
"element": 3,
"id": 1
}
]
}
]
Okay, so let's get some variables in:
const elementsData = [{ element: 0001, id: 1 }, { element: 0001, id: 2 }, { element: 0001, id: 3 }, { element: 0001, id: 4 }, { element: 0002, id: 1 }, { element: 0002, id: 2 }, { element: 0002, id: 3 }, { element: 0003, id: 1 } ]
First, You'll need to filter out the unique element values:
const uniqueElements = []
elementsData.forEach(datum => {
if (!uniqueElements.includes(datum.element)) {
uniqueElements.push(datum.element)
}
})
Then do groupings by uniqueElement
// loop through the unique Elements
const output = uniqueElements.map(uniqueElement => {
// this will return the object with the specified fields
return {
// element value
element: uniqueElement,
// filter through elementsData for matching elements and save then into an array.
// You can do sort() here if you want to sort them by id, but this is basically it
data: elementsData.filter(elementData => elementsData.element === uniqueElement)
}
})

MongoDB get remaining seats of restaurant

I've problem to find remaining seats of particular restaurant in a particular Date range
Let me define my problem. Suppose I've a collection it called booking
In this have a following fields:
Booking ID
User ID
Restaurant ID
Booking Start Date (date saved in Timestamp)
Booking End Date (date saved in Timestamp)
Booked Seat
If there are 50 seats in restaurant. And I want to check available seats of a particular date range for example the date range is 6-12(This range in timestamp)"(Start Date) - (End Date)"
How to calculate the total remaining seats of restaurant.
If anyone have any idea please let me know.
Thanks in advance
Code is here
const where = {};
where.restaurant_id = 126;
where.user_id = 1;
where.start_date = { $gte: 6 };
where.end_date = { $gte: 12 };
const remainingSeats = getSeatsAvailability(where);
function getSeatsAvailability(where) {
return new Promise((resolve, reject) => {
bookingModel.find(where, (err, details) => {
if (err) { reject(err); } else { resolve(details); }
});
});
}
So, What I have Visualized is the below diagram, so there are basically four cases to be covered:
x y
a-----------|---------b |
a-|------------|---b
| a-------b |
| a-----|--------b
So the formulae are:
1. a<x, a<y | b>x, b<y
2. a<x, a<y | b>x, b>y
3. a>x, a<y | b>x, b>y
4. a>x, a<y | b<y, b>x
I am pasting an ROUGH example, take it as a hint to solve the problem at hand:
db.collection.aggregate([
{
$match: {
$or: [
{
a: {
$lte: 3,
$lte: 9
},
$or: [
{
b: {
$gte: 3,
$lte: 9
}
},
{
b: {
$gte: 3,
$gte: 9
}
}
]
},
{
a: {
$gte: 3,
$lte: 9
},
$or: [
{
b: {
$gte: 3,
$gte: 9
}
},
{
b: {
$gte: 3,
$lte: 9
}
}
]
}
],
r: 1
}
},
{
$group: {
_id: null,
sum_booked: {
$sum: "$c"
}
}
},
{
$project: {
seats_left: {
$subtract: [
50,
"$sum_booked"
]
}
}
}
])
The example dataset that I have tested on:
[
{
a: 1,
b: 10,
c: 10,
r: 1,
},
{
a: 2,
b: 5,
c: 15,
r: 1
},
{
a: 5,
b: 10,
c: 10,
r: 1
},
{
a: 7,
b: 15,
c: 15,
r: 12 <<<<========/////DIFF REST ID
}
]
Output:
[
{
"_id": null,
"seats_left": 15
}
]
db.booking.aggregate([{
$match: {
BookingStartDate: { $lte: date_range_end },
BookingEndDate: { $gte: date_range_start },
RestaurantID: restaurant_id
}
},
{
$group: {
_id: '$RestaurantID',
TotalBookedSeat: { $sum: '$BookedSeat' }
}
},
{
$project: {
LeftSeat: { $subtract: [50, '$TotalBookedSeat'] },
_id: 0
}
}
])
{ "_id" : ObjectId("5d8479f6902a52448029a6d0"), "bid" : 1, "uid" : 1, "rid" : 126, "bsd" : 1, "bed" : 10, "bs" : 10 }
{ "_id" : ObjectId("5d847a11902a52448029a6d1"), "bid" : 2, "uid" : 1, "rid" : 126, "bsd" : 2, "bed" : 5, "bs" : 15 }
{ "_id" : ObjectId("5d847a24902a52448029a6d2"), "bid" : 3, "uid" : 1, "rid" : 126, "bsd" : 5, "bed" : 10, "bs" : 10 }
{ "_id" : ObjectId("5d847a34902a52448029a6d3"), "bid" : 4, "uid" : 1, "rid" : 126, "bsd" : 7, "bed" : 15, "bs" : 15 }
db.booking.aggregate([{ $match: { bsd: { $lte: 12 }, bed: { $gte: 6 }, rid: 126 } }, { $group: { _id: '$rid', total_seat_sold: { $sum: '$bs' } } }])
The result of the above is 35, then 15 seats left.
This time it will works I think.

How to sum distinct values of a field in a MongoDB collection (utilizing mongoose)

Imagine I had a collection called journals containing documents like the following:
{
"article": "id1",
"d": 2
},
{
"article": "id1",
"d": 2
},
{
"article": "id1",
"d": 3
},
{
"article": "id2",
"d": 2
},
...
Where d is kind of a switch and article is a reference. Now I want to have a result like the following:
[
{
"_id": "id1",
"total": 3,
"d2": 2,
"d3": 1
},
{
"_id": "id2",
"total": 1,
"d2": 1,
"d3": 0
}
]
I'm using mongoose and have a model called Journal. What I've got so far is…
Journal.aggregate(
{ $project: {
articleId: 1,
depth2 : { $gte:['$d', 2] },
depth3 : { $eq:['$d', 3] }
}},
{ $group: {
_id: '$article',
total: { $sum: 1 },
d2: { $sum: '$depth2'},
d3: { $sum: '$depth3'}
}
},
function (err, journal) {
console.log(journal);
}
);
which results in:
[
{
"_id": "id1",
"total": 3,
"d2": 0,
"d3": 0
},
{
"_id": "id2",
"total": 1,
"d2": 0,
"d3": 0
}
]
Obviously the error here is that $eq:['$d', 3] is not summed up because that results in a boolean.
So is there a better expression that projects the new depth2 and depth3 fields to 1or 0 instead of true or false?
Or is there a complete and better approach? :)
I'd like to avoid making 3 queries and prepending a matching phase like { $match: { d: 2 } }.
You can use $cond to convert a boolean to a numerical value, but you've also got a $gte where it seems an $eq should be and your docs use article while your code uses articleId:
Journal.aggregate([
{ $project: {
article: 1,
depth2 : { $cond: [{$eq: ['$d', 2]}, 1, 0] },
depth3 : { $cond: [{$eq: ['$d', 3]}, 1, 0] }
}},
{ $group: {
_id: '$article',
total: { $sum: 1 },
d2: { $sum: '$depth2'},
d3: { $sum: '$depth3'}
}
}
]);
Output:
{
"result" : [
{
"_id" : "id2",
"total" : 1,
"d2" : 1,
"d3" : 0
},
{
"_id" : "id1",
"total" : 3,
"d2" : 2,
"d3" : 1
}
],
"ok" : 1
}

Resources