How find consecutive results in mongoose - javascript

imagine I have the next collection:
Files
_id
code
randomid
ZA/1/1/1-1#1
randomid
ZA/1/1/1-1#2
randomid
ZA/1/1/1-1#3
randomid
ZA/1/1/1-1#10
randomid
ZA/1/1/1-1#12
randomid
ZA/1/1/1-1#12-1
randomid
ZA/1/1/1-1#12-2-1
randomid
ZA/1/1/1-1#12-2-2
randomid
ZA/1/1/1-1#120
And I'm trying to get the "Childs" using:
Model.find({ code: { $regex: 'ZA/1/1/1-1#12'} })
And what I want:
[
{
"_id": "randomid",
"code": "ZA/1/1/1-1#12"
"__v": 0
},
{
"_id": "randomid",
"code": "ZA/1/1/1-1#12-1"
"__v": 0
},
{
"_id": "randomid",
"code": "ZA/1/1/1-1#12-2-1"
"__v": 0
},
{
"_id": "randomid",
"code": "ZA/1/1/1-1#12-2-2"
"__v": 0
},
]
But Im getting (same but including the #120):
[
{
"_id": "randomid",
"code": "ZA/1/1/1-1#12"
"__v": 0
},
{
"_id": "randomid",
"code": "ZA/1/1/1-1#12-1"
"__v": 0
},
{
"_id": "randomid",
"code": "ZA/1/1/1-1#12-2-1"
"__v": 0
},
{
"_id": "randomid",
"code": "ZA/1/1/1-1#12-2-2"
"__v": 0
},
{
"_id": "randomid",
"code": "ZA/1/1/1-1#12-2-2"
"__v": 0
},
{
"_id": "randomid",
"code": "ZA/1/1/1-1#120"
"__v": 0
},
]
So, that's why I'm looking for help, how do I prevent this from happening?
Thanks.

If I understood your question correctly:
You want to get the children/consecutive items which might be defined with this code format:
ZA/1/1/1-1#12
ZA/1/1/1-1#12-SOMETHING
Which translates to ZA/1/1/1-1#12(\-.+)?$, or /ZA\/1\/1\/1\-1#12(\-.+)?$/.
These results match what you wanted
test> db.sth.find().pretty()
[
{ _id: 'randomid', code: 'ZA/1/1/1-1#12' },
{ _id: 'randomid', code: 'ZA/1/1/1-1#12-1' },
{ _id: 'randomid', code: 'ZA/1/1/1-1#12-2-2' },
{ _id: 'randomid', code: 'ZA/1/1/1-1#120' }
]
test> db.sth.find({ code: { $regex: "ZA/1/1/1-1#12(\-.+)?$"} }).pretty()
[
{ _id: 'randomid', code: 'ZA/1/1/1-1#12' },
{ _id: 'randomid', code: 'ZA/1/1/1-1#12-1' },
{ _id: 'randomid', code: 'ZA/1/1/1-1#12-2-2' }
]
test> db.sth.find({ code: { $regex: /ZA\/1\/1\/1\-1#12(\-.+)?$/} }).pretty()
[
{ _id: 'randomid', code: 'ZA/1/1/1-1#12' },
{ _id: 'randomid', code: 'ZA/1/1/1-1#12-1' },
{ _id: 'randomid', code: 'ZA/1/1/1-1#12-2-2' }
]

Related

mongodb update a value in array of object of array

i have a problem that i cannot resolved by myself.
i have a data in mongo db and i want to update specific value
i show the code and images
what i want is to update the specific object (the min propetry)
how i can update it?
await user.findOneAndUpdate(
{
name: "sss",
id: "test1",
decibelHistory: {
$elemMatch: { config: { min: 10 } },
},
},
{
$set: { "config.$.min": 1 },
}
);
{
"_id": {
"$oid": "638b39c2d96a4ac3ebb33c6b"
},
"name": "sss",
"password": "sss",
"decibelHistory": [
{
"id": "test1",
"config": [
{
"max": 90,
"min": 10,
"avg": 35
}
]
}
],
"timeLapse": 1200,
"__v": 0
}

Find user is registered to a Event in MongoDb (aggregation)

I tried to find users who are registered for that event.
So I join multiple collections shown below -
Events.aggregate([
{ $match: { category: "group_event" } },
// collection where events are scheduled
{
$lookup: {
from: "group_events",
let: { eventId: "$eventID" },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: ["$_id", "$$eventId"] },
{ $gt: ["$time", new Date()] },
],
},
},
},
// register user collection
{
$lookup: {
from: "register_events",
let: { eventId: "$_id" },
pipeline: [
{ $match: { $expr: { $eq: ["$eventId", "$$eventId"] } } },
],
as: "registerUsers",
},
},
],
as: "events",
},
},
{ $unwind: "$events" },
])
and the output is now comingout -
[
{
"_id": "614d6dfd82cb36be231083c9",
"trainerId": "61488dc36b7ccedbc884d20a",
"category": "group_event",
"eventID": "614d6dfc82cb36be231083c7",
"createdAt": "2021-09-24T06:19:41.268Z",
"updatedAt": "2021-09-24T06:19:41.268Z",
"__v": 0,
"events": {
"_id": "614d6dfc82cb36be231083c7",
"groupName": "group name 4",
"category": "sdfsdf",
"time": "2021-09-27T07:44:58.762Z",
"description": "description",
"day": "sunday",
"platform": "zoom",
"notes": "22",
"skills_to_learn": [
"demo"
],
"status": "pending",
"trainerId": "61488dc36b7ccedbc884d20a",
"meetingLink": "https://us05web.zoom.us/j/81660534858?pwd=cGZaODVjdWJUQWNtN243MlNiVUN0UT09",
"type": "group_event",
**isUserRegisted : true / false,**
"createdAt": "2021-09-24T06:19:41.000Z",
"updatedAt": "2021-09-24T06:19:41.000Z",
"__v": 0,
"registerUsers": [
{
"_id": "614ed6b4b8a545acb8517e85",
"userId": "614d59371d11becb8e23f536",
"eventId": "614d6dfc82cb36be231083c7",
"question": "",
"createdAt": "2021-09-25T07:58:44.939Z",
"updatedAt": "2021-09-25T07:58:44.939Z",
"__v": 0
}
]
}
}
]
which is ok for me bu just wanted to add a key: value, heighlited on obove section
isUserRegisted : true / false
i tried with $addFields but can't came up with any solution. Basically I need to retrieve arrays from registerUsers - collection and on the same time match the userId
I was able to figure out this issue.
simply I need to use $project and $filter to get the data if available and at last use $cond to return true or false
{
$project: {
root: "$$ROOT",
userFound: {
$filter: {
input: "$registerUsers",
as: "ac",
cond: {
$eq: ["$$ac.userId", mongoose.Types.ObjectId(userId)],
},
},
},
},
},
{
$project: {
_id: 0,
document: "$$ROOT",
userFound: {
$cond: {
if: { $isArray: "$userFound" },
then: {
$cond: {
if: {
$gt: [{ $size: "$userFound" }, 0],
},
then: true,
else: false,
},
},
else: false,
},
},
},
},
// merging nested object with parents
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
"$document.root",
{ isUserRegistered: "$userFound" },
],
},
},
},

How can I get count of the Documents and filter them in efficient way? (mongoose)

I'm implementing search function that is simply find document in mongoDB. I want to .skip(x) and .limit(x) on result to simulate paging result, but can I get total count of document (before skip and limit) and get filtered result at once?
Code that produce Expected Output :
db.Datas.find({ type: "Unknown" })
.then((result) => {
let count = result.length;
db.Datas.find({ type: "Unknown" })
.sort({ createdAt: -1 })
.skip((req.query.page - 1) * 10)
.limit(10)
.then((res) => {
res.json({ count: count, result: res });
});
})
.catch((err) => {});
But querying twice it somehow annoying, and it might be slow at large database.
I tried something like find({}).then(x => { ... }).sort(...) ... but isn't working because it only returns Promise.
How can I do this things in efficient way?
or is just getting whole documents and skip, limit with JS-way (using .splice, or etc..) will be faster and efficient?
You can use $facet aggregation to achieve this.
db.Datas.aggregate([
{
$match: {
"type": "Unknown"
}
},
{
$sort: {
createdAt: -1
}
},
{
$facet: {
totalRecords: [
{
$count: "total"
}
],
data: [
{
$skip: 0
},
{
$limit: 5
}
]
}
}
])
Playground
Let's say you have these documents:
db={
"Datas": [
{
"_id": "5e390fc33285e463a0799689",
"type": "Known",
"createdAt": "2020-02-04T06:31:31.311Z",
"__v": 0
},
{
"_id": "5e390fd03285e463a079968a",
"type": "Known",
"createdAt": "2020-02-04T06:31:44.190Z",
"__v": 0
},
{
"_id": "5e390fda3285e463a079968b",
"type": "Unknown",
"createdAt": "2020-02-04T06:31:54.248Z",
"__v": 0
},
{
"_id": "5e390fdf3285e463a079968c",
"type": "Unknown",
"createdAt": "2020-02-04T06:31:59.993Z",
"__v": 0
},
{
"_id": "5e390fec3285e463a079968d",
"type": "Unknown",
"createdAt": "2020-02-04T06:32:12.336Z",
"__v": 0
},
{
"_id": "5e390ffd3285e463a079968e",
"type": "Unknown",
"createdAt": "2020-02-04T06:32:29.670Z",
"__v": 0
},
{
"_id": "5e3910163285e463a079968f",
"type": "Unknown",
"createdAt": "2020-02-04T06:32:54.131Z",
"__v": 0
},
{
"_id": "5e3910213285e463a0799690",
"type": "Unknown",
"createdAt": "2020-02-04T06:33:05.166Z",
"__v": 0
}
]
}
Response will be like this:
[
{
"data": [
{
"__v": 0,
"_id": "5e3910213285e463a0799690",
"createdAt": "2020-02-04T06:33:05.166Z",
"type": "Unknown"
},
{
"__v": 0,
"_id": "5e3910163285e463a079968f",
"createdAt": "2020-02-04T06:32:54.131Z",
"type": "Unknown"
},
{
"__v": 0,
"_id": "5e390ffd3285e463a079968e",
"createdAt": "2020-02-04T06:32:29.670Z",
"type": "Unknown"
},
{
"__v": 0,
"_id": "5e390fec3285e463a079968d",
"createdAt": "2020-02-04T06:32:12.336Z",
"type": "Unknown"
},
{
"__v": 0,
"_id": "5e390fdf3285e463a079968c",
"createdAt": "2020-02-04T06:31:59.993Z",
"type": "Unknown"
}
],
"totalRecords": [
{
"total": 6
}
]
}
]
As you see, we got the total records with the filtered, sorted, skipped and limited data.

Creating a new table in mongoose based on object IDs

Hello the title of this question is very poorly worded however i will better explain the issue.
I have a document called 'buildings', and I also have two documents called 'rooms' and 'logins'. In both rooms and logins, they have an embedded document of building as follows:
Room Schema:
const roomSchema = new mongoose.Schema({
name: {
type: String,
required: true,
minlength: 1,
maxlength: 255
},
building: {
type: new mongoose.Schema({
name: {
type: String,
required: true,
minlength: 1,
maxlength: 255
}
}),
required: true
}
});
Logins Schema:
const loginSchema = new mongoose.Schema({
user: {
type: new mongoose.Schema({
email: {
type: String,
required: true
},
isVisitor: {
type: Boolean,
required: true
}
})
},
dateIn: {
type: Date,
required: true,
default: Date.now()
},
dateOut: {
type: Date
},
building: {
type: new mongoose.Schema({
name: {
type: String,
required: true
}
})
}
});
And the building schema is as follows:
const Building = mongoose.model(
"Building",
new mongoose.Schema({
name: {
type: String,
required: true,
minlength: 1,
maxlength: 255
},
address: {
type: String,
required: true,
minlength: 1,
maxlength: 255
},
postcode: {
type: String,
required: true,
minlength: 6,
maxlength: 8
},
organisation: {
type: new mongoose.Schema({
name: {
type: String,
required: true
}
})
}
})
);
Here is some examples of documents from each schema:
Building:
{
"_id": "5c79a31ed2016312ecd27c46",
"name": "TusPark",
"site": {
"_id": "5c79a243d2016312ecd27c45",
"name": "TusPark Newcastle"
},
"__v": 0
},
Rooms:
{
"_id": "5c7fa01abdd6233d6fdbc917",
"name": "E101",
"building": {
"_id": "5c79a31ed2016312ecd27c46",
"name": "TusPark"
},
"__v": 0
},
Logins:
{
"dateIn": "2019-03-21T13:13:23.069Z",
"_id": "5c938e151bd7a02d479893bd",
"user": {
"_id": "5c925378e88bb72764283108",
"email": "jack1#gmail.com",
"isVisitor": true
},
"building": {
"_id": "5c79a31ed2016312ecd27c46",
"name": "TusPark"
},
"__v": 0
}
I am trying to send a document to the client which contains the building details, with the rooms and logins embedded as attributes for the relevant building. The code I currently have written for this is below:
router.get("/all", async (req, res) => {
const buildings = await Building.find();
const rooms = await Room.find({
building_id: buildings._id
});
const logins = await Login.find({
building_id: buildings._id
});
const building_rooms = await Building.aggregate([
{
$lookup: {
from: "rooms",
localField: "building_id",
foreignField: "building_id",
as: "building_rooms"
}
},
{
$lookup: {
from: "logins",
localField: "building_id",
foreignField: "building_id",
as: "building_logins"
}
}
]);
res.send(building_rooms);
});
Note I have purposely not included $unwind
The current output for this request is:
[
{
"_id": "5c79a31ed2016312ecd27c46",
"name": "Park",
"site": {
"_id": "5c79a243d2016312ecd27c45",
"name": "Park Newcastle"
},
"__v": 0,
"building_rooms": [
{
"_id": "5c7fa01abdd6233d6fdbc917",
"name": "E101",
"building": {
"_id": "5c79a31ed2016312ecd27c46",
"name": "Park"
},
"__v": 0
},
{
"_id": "5c7fdbd12229db40589e41b5",
"name": "E202",
"building": {
"_id": "5c79a31ed2016312ecd27c46",
"name": "Park"
},
"__v": 0
}
],
"building_logins": [
{
"_id": "5c91483402d1a4145a2c4d9b",
"dateIn": "2019-03-19T19:51:06.458Z",
"user": {
"_id": "5c83b4b87321805bad025e65",
"email": "bob1999#gmail.com",
"isVisitor": true
},
"building": {
"_id": "5c79a31ed2016312ecd27c46",
"name": "Park"
},
"__v": 0,
"dateOut": "2019-03-20T11:55:19.205Z"
}
]
},
{
"_id": "5c925475e88bb72764283113",
"name": "Manchester",
"site": {
"_id": "5c921c94a922f6236cbe37d2",
"name": "Manchester"
},
"__v": 0,
"building_rooms": [
{
"_id": "5c7fa01abdd6233d6fdbc917",
"name": "E101",
"building": {
"_id": "5c79a31ed2016312ecd27c46",
"name": "Park"
},
"__v": 0
},
{
"_id": "5c7fdbd12229db40589e41b5",
"name": "E202",
"building": {
"_id": "5c79a31ed2016312ecd27c46",
"name": "Park"
},
"__v": 0
}
],
"building_logins": [
{
"_id": "5c91483402d1a4145a2c4d9b",
"dateIn": "2019-03-19T19:51:06.458Z",
"user": {
"_id": "5c83b4b87321805bad025e65",
"email": "bob1999#gmail.com",
"isVisitor": true
},
"building": {
"_id": "5c79a31ed2016312ecd27c46",
"name": "Park"
},
"__v": 0,
"dateOut": "2019-03-20T11:55:19.205Z"
}
]
}
]
However the issue is that the logins and rooms of 'Park' are being embedded in manchester building. which is not correct.
The correct output should be:
[
{
"_id": "5c79a31ed2016312ecd27c46",
"name": "Park",
"site": {
"_id": "5c79a243d2016312ecd27c45",
"name": "Park Newcastle"
},
"__v": 0,
"building_rooms": [
{
"_id": "5c7fa01abdd6233d6fdbc917",
"name": "E101",
"building": {
"_id": "5c79a31ed2016312ecd27c46",
"name": "Park"
},
"__v": 0
},
{
"_id": "5c7fdbd12229db40589e41b5",
"name": "E202",
"building": {
"_id": "5c79a31ed2016312ecd27c46",
"name": "Park"
},
"__v": 0
}
],
"building_logins": [
{
"_id": "5c91483402d1a4145a2c4d9b",
"dateIn": "2019-03-19T19:51:06.458Z",
"user": {
"_id": "5c83b4b87321805bad025e65",
"email": "bob1999#gmail.com",
"isVisitor": true
},
"building": {
"_id": "5c79a31ed2016312ecd27c46",
"name": "Park"
},
"__v": 0,
"dateOut": "2019-03-20T11:55:19.205Z"
}
]
},
{
"_id": "5c925475e88bb72764283113",
"name": "Manchester",
"site": {
"_id": "5c921c94a922f6236cbe37d2",
"name": "Manchester"
},
"__v": 0,
"building_rooms": [],
"building_logins": []
}
]
With there being no instances of building_rooms or building_logs as there are no logins or rooms with the object ID relating to manchester.
I really appreciate the time taken to read this and would be grateful for any help with solving tis problem.

Elasticsearch v6.0.1 Nodejs boost match with one of arrays elements

In my project I have user objects like this.
{
"_id": "1",
"username": "RAggro",
"name": "Vardan Tadevosyan"
},
{
"_id": "2",
"username": "XACHIK",
"name": "XACHIK"
},
{
"_id": "3",
"username": "vardar",
"name": "Vardan Gukoyan"
},
{
"_id": "4",
"username": "Gordey",
"name": "Gordey Gordeev"
},
{
"_id": "5",
"username": "id220107973",
"name": "Vardan Ayvazyan"
},
{
"_id": "6",
"username": "vvardanyan4",
"name": "Vardan Vardanyan"
},
{
"_id": "7",
"username": "svardan",
"name": "Vardan Sargsyan"
}
And I have list of _id-s, like [51,3,9,11,6, 2].
I whant to query users by 'name' and 'username', orderid like first comes users that contains in ids array then others
query: {
multi_match: {
query: "vardan",
fields: ["name", "username"],
operator: "or"
},
boosting: {
positive: {
term: {
_id: [51,3,9,11,6, 2]
}
},
positive_boost: 2.0
}
}
So the expected result is:
{
"_id": "3",
"username": "vardar",
"name": "Vardan Gukoyan"
},
{
"_id": "6",
"username": "vvardanyan4",
"name": "Vardan Vardanyan"
},
{
"_id": "1",
"username": "RAggro",
"name": "Vardan Tadevosyan"
},
{
"_id": "5",
"username": "id220107973",
"name": "Vardan Ayvazyan"
},
{
"_id": "7",
"username": "svardan",
"name": "Vardan Sargsyan"
}
But I'm fetching empty array,
Please, help how can I modify my query to reach expected ordered result.
You can do it easily using a bool/should clause that will boost the documents whose IDs are within the specified group:
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "vardan",
"fields": [
"name",
"username"
],
"operator": "or"
}
}
],
"should": [
{
"ids": {
"values": ["51","3","9","11","6","2"]
}
}
]
}
}
}
It works using this query:
{
query:{
"bool": {
"must": [{
"multi_match": {
"query": "vardan",
"fields": [
"name",
"username"
],
"operator": "or"
}
}],
"should": [{
"terms": {
"_id": ["51","3","9","11","6","2"],
"boost": 100
}
}]
}
}
}

Categories

Resources