Related
For one of my project, I am working on MongoDB database and Mongoose as ODM in nestjs project.
One of my collection is looks like this data:
[
{
_id: '56cb91bdc3464f14678934ca',
organization: 'New Circle Ltd',
rooms: [
{
name: 'Alex',
workId: 'abc',
},
{
name: 'John',
workId: 'cde',
},
{
name: 'John',
workId: 'abc',
},
{
name: 'Alex',
workId: 'cdlw',
},
{
name: 'Alex',
workId: 'rps',
},
],
},
];
The requirement is to get one data by id and the data should be like the data provided bellow.
{
_id: '56cb91bdc3464f14678934ca',
organization: 'New Circle Ltd',
rooms: [
{
name: 'Alex',
workIds: ['abc', 'cdlw', 'rps'],
},
{
name: 'John',
workIds: ['cde', 'abc'],
},
],
},
Please suggest me how can I get this data
I have this mongoose schema,
const Schema = mongoose.Schema;
const productSchema = new Schema({
name: { type: String, required: true },
image: { type: String, required: true },
saleSizes: [ //Sizes that a particular item has, ex.. Size P , M, G XG
{
saleSize: { type: String, required: true }, //actual sizes, ex.. P
price: { type: Number, required: true }, // sales price for size P
},
],
category: { type: String, required: true },
active: { type: Boolean, default: true },
});
const Product = mongoose.model('Product', productSchema);
module.exports = Product;
when I load the page , I use the find() method to list all my itens with the sale sizes and prices.
this is the function that i'm using.
function homeController() {
return {
async index(req, res) {
const products = await Product.find();
console.log(products);
const categories = [
...new Set(products.map((product) => product.category)),
];
return res.render('home', { products: products, categories: categories });
},
};
}
the return for the find() method is this.
[
{
active: true,
_id: 60affa70d981bc59b64f2e09,
name: 'Alface Americana',
image: 'alface-americana.png',
saleSizes: [ [Object], [Object] ],
category: 'Hortaliças'
},
{
active: true,
_id: 60affa70d981bc59b64f2e0a,
name: 'Couve',
image: 'Couve.png',
saleSizes: [ [Object], [Object] ],
category: 'Hortaliças'
},
{
active: true,
_id: 60affa70d981bc59b64f2e0b,
name: 'Agrião',
image: 'agriao.png',
saleSizes: [ [Object], [Object] ],
category: 'Hortaliças'
},
{
active: true,
_id: 60affa70d981bc59b64f2e0c,
name: 'Rúcula',
image: 'rucula.png',
saleSizes: [ [Object], [Object] ],
category: 'Hortaliças'
},
{
active: true,
_id: 60affa70d981bc59b64f2e0d,
name: 'Limão Taiti',
image: 'limao-taiti.png',
saleSizes: [ [Object], [Object] ],
category: 'Frutas'
},
{
active: true,
_id: 60affa70d981bc59b64f2e0e,
name: 'Goiaba Vermelha',
image: 'goiaba-vermelha.png',
saleSizes: [ [Object], [Object] ],
category: 'Frutas'
}
....
]
Note that saleSizes Properties return as array of objects.
saleSizes: [ [Object], [Object] ].
I need the return to be something like this.
{
active: true,
_id: 60affa70d981bc59b64f2e18,
name: 'Granola',
image: 'granola.png',
price: '500',
saleSizes: [
{saleSize: "P", price: "100"},
{saleSize: "G", price: "200"}
],
category: 'Grãos'
}
what is the best approach to accomplish that?.
PS: sorry for my English, i'm from Brasil and still Learning (I think this is a forever process).
It is returned correctly. saleSizes is the array of Objects. {saleSize: "P", price: "100"} is Object. You can try to access those nested objects like this:
let size = saleSizes[0].saleSize;
let price = saleSizes[0].price;
After Nenad Milosavljevic comment, I change my html code to this.
<% product.saleSizes.forEach(function (saleSize){%>
<span class="font-bold text-lg">R$ <%= saleSize.price %></span>
<button
type="button"
class="size py-1 px-4 rounded-full uppercase text-xs"
><%= saleSize.saleSize %>
</button>
<% })%>
I'm using EJS by the way, now I have a button for each sale Size and a price as well.
Thank You so much for the Help, I was trying to solve a problem that isn't a problem.
I am following this toutorial: https://github.com/codeBelt/open-api-documentation/blob/master/src/openApiDocumentation.js
Can I validate my openApiDocumentation.js file somewhow? I get:
Unable to render this definition
The provided definition does not specify a valid version field.
Please indicate a valid Swagger or OpenAPI version field. Supported version fields are swagger: "2.0" and those that match openapi: 3.0.n (for example, openapi: 3.0.0).
I am attaching mi .js file. Maybe you guys will see a typo here. Thanks in advance.
.js file:
const USER_TYPES = {
EXCHANGE: 'xxx',
GIVEAWAY: 'xxx'
}
const openApiDocumentation = {
openapi: '3.0.1',
info: {
version: '1.3.0',
title: 'xxx',
description: 'xxx',
contact: {
name: 'xxx',
email: 'xxx',
}
},
license: {
name: 'Apache 2.0',
url: 'https://www.apache.org/licenses/LICENSE-2.0.html',
},
servers: [
{
url: 'http://localhost:4000/',
description: 'Local server',
},
],
tags: [
{
name: 'Books CRUD operations',
},
],
paths: {
'/findAllBooks': {
get: {
tags: ['CRUD operations'],
description: 'Get all Book offers',
operationId: 'getUsers',
parameters: [
{
name: 'page',
in: 'query',
schema: {
type: 'integer',
default: 1,
},
required: true,
description: 'Page numer used pagination.',
},
],
responses: {
'200': {
description: 'Books were obtained',
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/Books',
},
},
},
},
'500': {
description: 'Missing parameters',
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/Error',
},
example: {
message: 'page qyery parameter is missing',
internal_code: 'missing_parameters',
},
},
},
},
},
},
},
},
components: {
schemas: {
coverImg: {
type: 'string',
example: 'http:',
},
image: {
type: 'string',
example: 'http',
},
category: {
type: 'string',
example: 'Crafts & Hobbies',
},
linkTypes: {
type: 'object',
properties: {
coverImg: {
$ref: '#/components/schemas/coverImg',
},
images: {
type: 'array',
items: {
$ref: '#/components/schemas/image',
},
}
}
},
offerID: {
type: 'string',
example: '27301927',
},
userID: {
type: 'string',
example: 'efdc5192',
},
title: {
type: 'string',
example: 'Quilting For Dummies',
},
description: {
type: 'string',
example: 'You ',
},
categories: {
type: 'array',
items: {
$ref: '#/components/schemas/category',
},
},
links: {
type: 'object',
items: {
$ref: '#/components/schemas/linkTypes',
},
},
offerType: {
type: 'string',
enum: USER_TYPES,
default: USER_TYPES.EXCHANGE,
},
Book: {
type: 'object',
properties: {
offerID: {
$ref: '#/components/schemas/offerID',
},
userID: {
$ref: '#/components/schemas/userID',
},
title: {
$ref: '#/components/schemas/title',
},
description: {
$ref: '#/components/schemas/description',
},
categories: {
$ref: '#/components/schemas/categories',
},
imageLinks: {
$ref: '#/components/schemas/links',
},
offerType: {
$ref: '#/components/schemas/offerType',
},
},
},
Books: {
type: 'object',
properties: {
users: {
type: 'array',
items: {
$ref: '#/components/schemas/Book',
},
},
},
},
Error: {
type: 'object',
properties: {
message: {
type: 'string',
},
internal_code: {
type: 'string',
},
},
},
},
},
};
There are few mistakes,
license must be inside the info object
info: {
version: '1.3.0',
title: 'xxx',
description: 'xxx',
contact: {
name: 'xxx',
email: 'xxx' // make sure you have used valid email address!
},
license: {
name: 'Apache 2.0',
url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
}
}
enum will allow only array not an object and here you have passed object USER_TYPES, corrected below:
const USER_TYPES = {
EXCHANGE: 'xxx',
GIVEAWAY: 'xxx'
};
const USER_TYPES_ENUM = [
USER_TYPES.EXCHANGE,
USER_TYPES.GIVEAWAY
];
offerType: {
type: 'string',
enum: USER_TYPES_ENUM,
default: USER_TYPES.EXCHANGE,
},
For best practice use https://editor.swagger.io/ (also they have provided a option to convert json to yaml under Edit > Convert to YAML)!
I apologize if answers exist elsewhere, please redirect me. I'm using node.js, express, & ejs.
server.js
//API v4//media
const mediaAPI = { method: 'GET',
url: 'https://api.media.com/v4/media',
qs:
{ access_token: 'abc123'
}
};
//media data
app.get('/media', function (req, res) {
try {
request(mediaAPI, function (error, response, body) {
if (error) throw new Error(error);
const mediaphotos = JSON.parse(body);
const mediaphotolist = mediaphotos.response.checkins.items.map(item => item );
res.render('media.ejs', {mediaphotolist});
console.log(mediaphotolist);
});
} catch(e) {
console.log("Something went wrong", e)
}
});
Based on this code, I can see the following array in my console.log(mediaphotolist). Please note, there are multiple items returned, I'm only showing one to save space.
[ { uid: 123456789,
person:
{ uid: 1234,
first_name: 'frank',
last_name: 'doe',
contact: [Object] },
house:
{ hid: 5724,
house_name: 'Peterson House',
house_style: 'Modern' },
neighborhood:
{ nid: 379,
neighborhood_name: 'Dexter',
neighborhood_type: 'Old' },
media: { count: 1, items: [Array] }
} ]
There is an image URL inside of the media: [Array] that I want to get. As seen inside postman, it looks like this...
media: {
count: 1,
items: [
{
photo_id: 1234,
photo: {
photo_img_sm: https://media.net/photos/123_200x200.jpg,
photo_img_md: https://media.net/photos/456_640x640.jpg,
photo_img_lg: https://media.net/photos/789_1280x1280.jpg
}
}
]
}
In my media.ejs file I have the following ejs code to display first_name and photo_img_sm...
media.ejs
<ul>
<% mediaphotolist.forEach(function(photoofhouse){ %>
<div>
<li>
<p>First Name: <%= photoofhouse.person.first_name %></p>
<img src= "<%= photoofhouse.media.items.photo.photo_img_sm %>" alt="">
</li>
</div>
<% }) %>
</ul>
I can make the first_name show using the ejs script seen above, but, I don't know know to dig deeper to get the photo_img_sm object that lives within these nested arrays and objects. I'm hoping I don't have to change my server side code and simply learn the proper syntax for accessing this photo_img_sm object.
According to your code, media.items is an array. So every media may have more than one items and photos. If you want to display the first item photo you should use this code
<img src= "<%= photoofhouse.media.items[0].photo.photo_img_sm %>" alt="">
In case you have more than one items inside media and want to display them all, you have to loop the media.items array like this:
<% mediaphotolist.forEach(function(photoofhouse){ %>
<div>
<li>
<p>First Name: <%= photoofhouse.person.first_name %></p>
<% photoofhouse.media.items.forEach(function(el){ %>
<img src= "<%= el.photo.photo_img_sm %>" alt="">
<% }) %>
</li>
</div>
<% }) %>
I've used this as an example hope you can apply it to your scenario say you the variable is named bg
hence
let bg = [ { uid: 123456789,
person:
{ uid: 1234,
first_name: 'frank',
last_name: 'doe',
contact: [Object] },
house:
{ hid: 5724,
house_name: 'Peterson House',
house_style: 'Modern' },
neighborhood:
{ nid: 379,
neighborhood_name: 'Dexter',
neighborhood_type: 'Old' },
media: {
items: [
{
photo_id: 1234,
photo: {
photo_img_sm: 'https://media.net/photos/123_200x200.jpg',
photo_img_md: 'https://media.net/photos/456_640x640.jpg',
photo_img_lg: 'https://media.net/photos/789_1280x1280.jpg'
}
}
]
}} ]
You could access the photos like this
bg[0].media["items"][0]["photo"]
or using the dot notation
bg[0].media["items"][0].photo
if there were multiple items like you said you have
let gb = [ { uid: 123456789,
person:
{ uid: 1234,
first_name: 'frank',
last_name: 'doe',
contact: [Object] },
house:
{ hid: 5724,
house_name: 'Peterson House',
house_style: 'Modern' },
neighborhood:
{ nid: 379,
neighborhood_name: 'Dexter',
neighborhood_type: 'Old' },
media: {
items: [
{
photo_id: 1234,
photo: {
photo_img_sm: 'https://media.net/photos/123_200x200.jpg',
photo_img_md: 'https://media.net/photos/456_640x640.jpg',
photo_img_lg: 'https://media.net/photos/789_1280x1280.jpg'
}
}
]
}
} ,{ uid: 123456789,
person:
{ uid: 1234,
first_name: 'frank',
last_name: 'doe',
contact: [Object] },
house:
{ hid: 5724,
house_name: 'Peterson House',
house_style: 'Modern' },
neighborhood:
{ nid: 379,
neighborhood_name: 'Dexter',
neighborhood_type: 'Old' },
media: {
items: [
{
photo_id: 1234,
photo: {
photo_img_sm: 'https://media.net/photos/123_200x200.jpg',
photo_img_md: 'https://media.net/photos/456_640x640.jpg',
photo_img_lg: 'https://media.net/photos/789_1280x1280.jpg'
}
}
]
}
},{ uid: 123456789,
person:
{ uid: 1234,
first_name: 'frank',
last_name: 'doe',
contact: [Object] },
house:
{ hid: 5724,
house_name: 'Peterson House',
house_style: 'Modern' },
neighborhood:
{ nid: 379,
neighborhood_name: 'Dexter',
neighborhood_type: 'Old' },
media: {
items: [
{
photo_id: 1234,
photo: {
photo_img_sm: 'https://media.net/photos/123_200x200.jpg',
photo_img_md: 'https://media.net/photos/456_640x640.jpg',
photo_img_lg: 'https://media.net/photos/789_1280x1280.jpg'
}
}
]
}
},{ uid: 123456789,
person:
{ uid: 1234,
first_name: 'frank',
last_name: 'doe',
contact: [Object] },
house:
{ hid: 5724,
house_name: 'Peterson House',
house_style: 'Modern' },
neighborhood:
{ nid: 379,
neighborhood_name: 'Dexter',
neighborhood_type: 'Old' },
media: {
items: [
{
photo_id: 1234,
photo: {
photo_img_sm: 'https://media.net/photos/123_200x200.jpg',
photo_img_md: 'https://media.net/photos/456_640x640.jpg',
photo_img_lg: 'https://media.net/photos/789_1280x1280.jpg'
}
}
]
}
},{ uid: 123456789,
person:
{ uid: 1234,
first_name: 'frank',
last_name: 'doe',
contact: [Object] },
house:
{ hid: 5724,
house_name: 'Peterson House',
house_style: 'Modern' },
neighborhood:
{ nid: 379,
neighborhood_name: 'Dexter',
neighborhood_type: 'Old' },
media: {
items: [
{
photo_id: 1234,
photo: {
photo_img_sm: 'https://media.net/photos/123_200x200.jpg',
photo_img_md: 'https://media.net/photos/456_640x640.jpg',
photo_img_lg: 'https://media.net/photos/789_1280x1280.jpg'
}
}
]
}
}]
You could iterate through each and still access the photo variable
like so
gb.forEach(onePhoto =>{ for (d in onePhoto["media"]['items'][0].photo){console.log(onePhoto["media"]['items'][0].photo[d])}})
I have an SDK 4 bot, logging user interactions to Blob storage. I would also like to log bot responses also. In SDK 3 I did this with something like ...
bot.use({
// Code for handling message receives
receive: function (session, event, next) {
var userId = session.address.user.id;
logger.logUserConversation(session.text, userId, session.address.conversation.id, userId);
next();
},
// Code for handling message sends
send: function (event, next) {
var text = event.text;
if(!event.text) {
text = "Attachments sent";
}
logger.logUserConversation(text, 'bot', event.address.conversation.id, event.address.user.id);
next();
}
});
In SDK 4, I am able to configure middleware which intercepts user activity, but I cannot seem to intercept bot activity. I can't seem to find anything in the documentation, but I am new to SDK 4 and might be missing something.
Anybody know how I can intercept both user and bot events, so that I can log?
There are already 2 samples in Node.js in the official samples repository:
1 called "Logger": https://github.com/Microsoft/BotBuilder-Samples/tree/master/samples/javascript_nodejs/25.logger
1 called "transcript Logger": https://github.com/Microsoft/BotBuilder-Samples/tree/master/samples/javascript_nodejs/26.transcript-logger
I gave a try to the 1st one and can confirm that it logs both user input and bot replies. It is logging every activity, even ConversationUpdate.
See example of transcript generated below:
Activity Received: { type: 'conversationUpdate',
membersAdded: [ { id: '1', name: 'Bot' } ],
channelId: 'emulator',
conversation: { id: '36e25420-ec19-11e8-8040-2ba105e71021|livechat' },
id: '370f7ea0-ec19-11e8-9ee4-fb60855d29c5',
localTimestamp: 2018-11-19T16:36:07.000Z,
recipient: { id: '1', name: 'Bot', role: 'bot' },
timestamp: 2018-11-19T16:36:07.689Z,
from:
{ id: 'fd3fd64d-6297-4e36-98c5-ee398857f2b6',
name: 'User',
role: 'user' },
locale: '',
serviceUrl: 'http://localhost:58083' }
Activity Received: { type: 'conversationUpdate',
membersAdded:
[ { id: 'fd3fd64d-6297-4e36-98c5-ee398857f2b6', name: 'User' } ],
channelId: 'emulator',
conversation: { id: '36e25420-ec19-11e8-8040-2ba105e71021|livechat' },
id: '3711c890-ec19-11e8-9ee4-fb60855d29c5',
localTimestamp: 2018-11-19T16:36:07.000Z,
recipient: { id: '1', name: 'Bot', role: 'bot' },
timestamp: 2018-11-19T16:36:07.705Z,
from:
{ id: 'fd3fd64d-6297-4e36-98c5-ee398857f2b6',
name: 'User',
role: 'user' },
locale: '',
serviceUrl: 'http://localhost:58083' }
Activity Received: { text:
'I am a bot that demonstrates custom logging. We will have a short conversation where I ask a few questions to collect your name and age, then store those values in UserState for later use. after this you will be able to find a log of the conversation in the folder set by the transcriptsPath environment variable Say anything to continue.',
inputHint: 'acceptingInput',
channelId: 'emulator',
serviceUrl: 'http://localhost:58083',
conversation: { id: '36e25420-ec19-11e8-8040-2ba105e71021|livechat' },
from: { id: '1', name: 'Bot', role: 'bot' },
recipient:
{ id: 'fd3fd64d-6297-4e36-98c5-ee398857f2b6',
name: 'User',
role: 'user' },
replyToId: '3711c890-ec19-11e8-9ee4-fb60855d29c5',
type: 'message',
timestamp: 2018-11-19T16:36:08.408Z }
Activity Received: { type: 'message',
text: 'test',
from:
{ id: 'fd3fd64d-6297-4e36-98c5-ee398857f2b6',
name: 'User',
role: 'user' },
locale: '',
textFormat: 'plain',
timestamp: 2018-11-19T16:36:23.421Z,
channelData: { clientActivityId: '1542645367574.7109285295569892.0' },
entities:
[ { type: 'ClientCapabilities',
requiresBotState: true,
supportsTts: true,
supportsListening: true } ],
channelId: 'emulator',
conversation: { id: '36e25420-ec19-11e8-8040-2ba105e71021|livechat' },
id: '406fdad0-ec19-11e8-9ee4-fb60855d29c5',
localTimestamp: 2018-11-19T16:36:23.000Z,
recipient: { id: '1', name: 'Bot', role: 'bot' },
serviceUrl: 'http://localhost:58083' }
Activity Received: { text: 'What is your name, human?',
inputHint: 'expectingInput',
channelId: 'emulator',
serviceUrl: 'http://localhost:58083',
conversation: { id: '36e25420-ec19-11e8-8040-2ba105e71021|livechat' },
from: { id: '1', name: 'Bot', role: 'bot' },
recipient:
{ id: 'fd3fd64d-6297-4e36-98c5-ee398857f2b6',
name: 'User',
role: 'user' },
replyToId: '406fdad0-ec19-11e8-9ee4-fb60855d29c5',
type: 'message',
timestamp: 2018-11-19T16:36:23.443Z }
More details about the code that generated that is available on the project, here. If you look at it, the main point is:
if (activity.value === 'endOfInput') {
console.log(this.conversations[id]);
var transcriptfileName = util.format('%s/log_%s.transcript', process.env.transcriptsPath, id);
fs.writeFile(transcriptfileName, JSON.stringify(this.conversations[id], null, 3), function(err) {
if (err) throw err;
});
delete this.conversations[id];
}