Mongodb find by Id in Es6 and moongose doesnt work - mongodb

SO i try to query data using mongodb on ES6 using this query:
const { title = "", date1 = "", user = "", date2 = "" } = req.query;
const formIds = req.params.formId;
let forms = "";
if (date2 === "undefined") {
console.log(date1, date2, formIds);
}
const form = await Form.findOne({
_id: req.params.formId,
});
if (!form) {
throw { code: 404, message: "FORM_NOT_FOUND" };
}
console.log(form.id);
if (date2 === "undefined") {
forms = await Answer.aggregate([
{
$match: {
$and: [{ date: date1 }, { formId: o_id }],
},
},
{
$group: {
_id: "$title",
title: {
$first: "$title",
},
answer: {
$push: {
username: "$username",
date: "$date",
formId: "$formId",
answers: "$answer",
},
},
},
},
]);
}
but because it using ObjectId on Mongo.., i cannot return the value even though it has the value on the database with format like this:
{
"_id": {
"$oid": "636242358721c33778b16e0f"
},
"userId": {
"$oid": "6355d841bf2fc81f76edfbd9"
},
"formId": {
"$oid": "6361c5aaf7a02c177ebebb27"
},
"title": "Untitled Form",
"username": "jansenstan2410#gmail.com",
"date": "2022-11-02",
"answer": {
"Test": [
"New Option"
],
"Email": "john#nabatisnack.com",
"Dropdown": "New Option",
"Radio": "3",
"Date": "2022-11-01T00:00:00.000Z",
"Time": "17:25"
}
}
can someone tell me where did i do wrong here?i try to find answer all the answer using require while in ES6 i use mongoose

Related

How to perform two group bys in one aggregation query in mongoose?

I'm a beginner trying to create an API using express ang mongodb and this is my first time posting a question here, so forgive me if my question sounds stupid.
I have this data:
Restaurants
[
{
"_id": "630c0d5e82d52d0852d34b11",
"name": "Restaurant 1",
"type": "Fine Dining",
"cuisine": "Korean",
},
{
"_id": "630c0d5e82d52d0852d34b12",
"name": "Restaurant 2",
"type": "Fine Dining",
"cuisine": "International",
},
{
"_id": "630c0d5e82d52d0852d34b13",
"name": "Restaurant 3",
"type": "Casual Dining",
"cuisine": "Korean",
},
{
"_id": "630c0d5e82d52d0852d34b14",
"name": "Restaurant 4",
"type": "Casual Dining",
"cuisine": "International",
},
...
]
so what I want to achieve is when I create a GET request to this API endpoint http://localhost:8000/api/v1/restaurants/stats is this:
{
"status": "success",
"data": {
"cuisines": [
{
"_id": "Korean",
"restaurants": ["630c0d5e82d52d0852d34b11", "630c0d5e82d52d0852d34b13"],
"quantity": 2
},
{
"_id": "International",
"restaurants": ["630c0d5e82d52d0852d34b12", "630c0d5e82d52d0852d34b14"],
"quantity": 2
}
],
"type": [
{
"_id": "Casual Dining",
"restaurants": ["630c0d5e82d52d0852d34b14", "630c0d5e82d52d0852d34b13"],
"quantity": 2
},
{
"_id": "Fine Dining",
"restaurants": ["630c0d5e82d52d0852d34b11", "630c0d5e82d52d0852d34b12"],
"quantity": 2
}
]
}
}
This is what I have tried so far
restaurantController.js
...
exports.getRestaurantStats = async (req, res) => {
const cuisines = await Restaurant.aggregate([
{
$group: {
_id: '$cuisine',
restaurants: { $push: '$_id' },
quantity: { $sum: 1 },
}
},
]);
res.status(200).json({
status: 'success',
data: {
cuisines,
},
});
};
...
restaurantRoutes.js
...
router.route('/stats').get(restaurantController.getRestaurantStats);
...
The result for calling this endpoint http://localhost:8000/api/v1/restaurants/stats
{
"status": "success",
"data": {
"cuisines": [
{
"_id": "Korean",
"restaurants": ["630c0d5e82d52d0852d34b11", "630c0d5e82d52d0852d34b13"],
"quantity": 2
},
{
"_id": "International",
"restaurants": ["630c0d5e82d52d0852d34b12", "630c0d5e82d52d0852d34b14"],
"quantity": 2
}
]
}
But when I add this another group by
...
$group: {
_id: '$type',
restaurants: { $push: '$_id' },
quantity: { $sum: 1 },
}
...
to restaurantController.js
...
exports.getRestaurantStats = async (req, res) => {
const cuisines = await Restaurant.aggregate([
{
$group: {
_id: '$cuisine',
restaurants: { $push: '$_id' },
quantity: { $sum: 1 },
},
$group: {
_id: '$type',
restaurants: { $push: '$_id' },
quantity: { $sum: 1 },
}
},
]);
res.status(200).json({
status: 'success',
data: {
cuisines,
},
});
};
...
the result is different. Its seems like it overwrote the first group by in the pipeline.

Mongoose, aggregate query with $lookup return null?

varyantalt Model:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const varyantaltSchema = new Schema({
_id: {
type: Schema.ObjectId
},
varyantid: {
type: String
},
altvaryantname: {
type: String
},
createdAt: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model("varyantalt", varyantaltSchema, "varyantalt");
varyant model:
const varyantSchema = new Schema({
_id: {
type: Schema.ObjectId
},
stokid: {
type: Schema.ObjectId
},
varyantname: {
type: String
},
createdAt: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model("varyant", varyantSchema, "varyant");
varyant collection:
{
"_id": ObjectId("5e32286c34fb7322bdd566ed"),
"stokid": ObjectId("5e28b4a2a1d9692b29a65b24"),
"varyantname": "RENK"
}
altvaryant collection:
{
"_id": ObjectId("5e3228df34fb7322bdd566f5"),
"varyantid": "5e32286c34fb7322bdd566ed",
"altvaryantname": "KIRMIZI",
"vars": [
{
"_id": ObjectId("5e35b1e410fce83f3370cd0a"),
"images": {
"imageurl": "http://",
"_id": ObjectId("5e35b1e410fce83f3370cd0b"),
"filename": "5320_7d93",
"path": "https://res",
"publicid": "panel"
}
}
]
},
{
"_id": ObjectId("5e3359e6fa4c5e4bd9112fb6"),
"varyantid": "5e32286c34fb7322bdd566ed",
"altvaryantname": "SARI",
"vars": [
{
"_id": ObjectId("5e35b1f610fce83f3370cd0d"),
"images": {
"imageurl": "http://",
"_id": ObjectId("5e35b1f610fce83f3370cd0e"),
"filename": "veli-fidan-1LT-2-450x450",
"path": "https://",
"publicid": "panel"
}
}
]
},
{
"_id": ObjectId("5e335b64fa4c5e4bd9112fc9"),
"varyantid": "5e32286c34fb7322bdd566ed",
"altvaryantname": "YEŞİL",
"vars": [
{
"_id": ObjectId("5e35b20010fce83f3370cd10"),
"images": {
"imageurl": "http://",
"_id": ObjectId("5e35b20010fce83f3370cd11"),
"filename": "maxresdefault-29-450x450",
"path": "https://",
"publicid": ""
}
}
]
}
Query:
varyant
.aggregate([
{
$match: {
stokid: mongoose.Types.ObjectId("5e28b4a2a1d9692b29a65b24")
}
},
{
$lookup: {
from: "varyantalt",
localField: "_id",
foreignField: "varyantid",
as: "vars"
}
},
{ $unwind: "$vars" }
])
.exec((err, locations) => {
if (err) throw err;
console.log("res::", locations);
});
I am trying to get results with $aggregate and $lookup query with mongoose
Why is my query returning empty? I couldn't find the problem.
Under $lookup operator from: 'varyantalt' I do not understand exactly whether it takes a blank value. Thanks in advance for your help.
In your varyantaltSchema schema, varyantid is defined as String, but it must be Schema.ObjectId.
They must be same because $lookup performs an equality match on the foreignField to the localField from the input documents
If you save your varyandid as Object id aggregate will work.

Mongoose aggregate with nested collection

I have following schemas.
First: AdditionalFieldSchema
const AdditionalFieldSchema = new Schema({
names: [
{
type: Schema.Types.ObjectId,
ref: "multiLanguageContent",
required: true
}
],
...
});
Second: MultiLanguageContentSchema
const MultiLanguageContentSchema = new Schema({
value: {
type: String,
required: true
},
...
});
and I have the following mongoose aggregate query.
The goal is to fetch every employees with their additionalField attached.
const employees = await Employee.aggregate([
{
$match: {
status: "active",
$nor: [
{ email: "blablabla" },
{ email: "blobloblo" }
]
}
},
{
$lookup: {
from: AdditionalField.collection.name,
let: { af_id: "$_id" },
pipeline: [{
$match: {
$expr: {
$and: [
{ $eq: ["$ownership", "$$af_id"] },
{ $eq: ["$status", "active"] },
{ $eq: ["$functionalType", "blablabla"] }
]
}
}
}],
as: "afs"
}
},
{ $unwind: "$afs" },
{ $unwind: "$afs.names" },
{
$group: {
_id: "$_id",
email: { $first: "$email" },
afs: {
$push: {
value: "$afs.value",
names: "$afs.names"
}
}
}
}
]);
The query I run to test this aggregate function.
query TestQuery {
testQuery
{
email
afs {
names {
value
}
value
}
}
}
The result I have.
"data": {
"testQuery": [
{
"email": "blablabla#test.com"
"afs": [
{
"names": [
{
"value": "Name 1"
}
],
"value": "Value 1"
},
{
"names": [
{
"value": "Name 2"
}
],
"value": "Value 2"
},
...
]
},
...
Result is good, I have data I want.
But I would like to have a result like this below
"data": {
"testQuery": [
{
"email": "blablabla#test.com",
"afs": [
{
"names": "Name 1",
"value": "Value 1"
},
{
"names": "Name 2",
"value": "Value 2"
},
...
]
},
...
It seems like { $unwind: "$afs.names" }, is not working.
Any ideas ?
Thanks, Flo

using $elemMatch in projection with field choosing

I'm trying to select only some fields in document while also using $elemmatch. It turned out the field selection is getting ignored.
Given a document like this:
{
"author": "Robin Sharma",
"data": [
{
"translation": "en",
"content": "foo",
"unwanted_content": "huyu1",
},
{
"translation": "id",
"content": "bar",
"unwanted_content": "huyu2",
{
],
}
I'm using find() with this projection config:
const projection = {
author: 1,
data: {
$elemMatch: {
translation: "en"
},
},
}
Expected
{
"author": "Robin Sharma",
"data": [
{
"translation": "en",
"content": "foo"
},
],
}
Actual
{
"author": "Robin Sharma",
"data": [
{
"translation": "en",
"content": "foo",
"unwanted_content": "huyu1",
},
],
}
I'm still not sure how to get rid of the "unwanted_content" field.
You can achieve your required result using aggregate as:
db.collection.aggregate([
{
$unwind: "$data"
},
{
$match: {
"data.translation": "en"
}
},
{
$group: {
_id: "$author",
data: {
$push: {
translation: "$data.translation",
content: "$data.content"
}
}
}
}
])
I think you can do something like this to get only selected fields from subdocument.
db.collection.find({"data.translation": "en"},{author: 1, "data.content": 1, "data.translation": 1})

Get length of array within array mongodb

I'm trying to count the number of votes per question for the following schema.
[
{
"_id": "564b9e13583087872176dbd2",
"question": "fav NFL team",
"choices": [
{
"text": "St. Louis Rams",
"_id": "564b9e13583087872176dbd7",
"votes": [
{
"ip": "::ffff:192.168.15.130",
"_id": "564b9e30583087872176dbd8"
},
{
"ip": "::ffff:192.168.1.1",
"_id": "564bb355e4e1b7200da92668"
}
]
},
{
"text": "Oakland Raiders",
"_id": "564b9e13583087872176dbd6",
"votes": [
{
"ip": "::ffff:192.168.1.135",
"_id": "564bb273e4e1b7200da92667"
}
]
},
{
"text": "Denver Broncos",
"_id": "564b9e13583087872176dbd5",
"votes": []
},
{
"text": "Kansas City Chiefs",
"_id": "564b9e13583087872176dbd4",
"votes": [
{
"ip": "::ffff:192.168.1.100",
"_id": "564bab48e4e1b7200da92666"
}
]
},
{
"text": "Detroit Lions",
"_id": "564b9e13583087872176dbd3",
"votes": [
{
"ip": "::ffff:192.168.15.1",
"_id": "564b9f41583087872176dbd9"
}
]
}
]
}
]
I'm assuming I am going to have to use aggregate and sum.
I was able to get the count for the choices array, but I'm not sure how to go deeper.
db.polls.aggregate([{$unwind: '$choices'}, {$group:{_id:'$_id', 'sum':{$sum:1}}}])
The vote count for "fav NFL team" would be 5.
Also, for reference here is my mongoose code that generated the schema
var mongoose = require('mongoose');
var voteSchema = new mongoose.Schema({
ip: 'String'
});
var choiceSchema = new mongoose.Schema({
text: String,
votes: [voteSchema]
});
exports.PollSchema = new mongoose.Schema({
question: {
type: String,
required: true
},
choices: [choiceSchema]
});
I figured out how to do it in mango, I needed another unwind.
db.polls.aggregate([
{$unwind: '$choices'},
{$unwind:'$choices.votes'},
{$group:{
_id:'$_id',
'sum':{
$sum:1
}
}}
])
And here it is in mongoose
Poll.aggregate([
{$unwind: '$choices'},
{$unwind: '$choices.votes'},
{$group:{
_id: '$_id',
'sum': {
$sum:1
}
}}
], function(err, result) {
if (err) {
console.log(err);
}
res.json(result);
});