Storing an Array of String to a Key in MongoDB - javascript

I'm building a post request which will contain various info on each role. E.g in this trial, 'Data Analyst'.
In this position I want to have quite a few sources of data, including things like salary, education and skills.
However, I'm using recharts to visualise it, which means although I need a key, e.g Masters's degree, I also need a num value associated, such as below:
const educationData = [
{
degree: 'Masters',
A: 120,
},
{
degree: 'Bachelor',
A: 98,
},
{
degree: 'PhD',
A: 86,
},
{
degree: 'Industry',
A: 99,
},
{
degree: 'Associate',
A: 85,
}
];
I would like to store this inside my schema created:
const RolesPositionSchema = new mongoose.Schema(
{
title:{type:String, required: true, unique: true},
desc:{type:String, required: true},
skills:{type:Array, required: true},
salary:{type:Array},
education: {type: Array},
popularity: {type: Number},
reccomendations: {type: Array},
},
);
Within this I would like to store the 'educationData' into the DB. Happy to input it in manually for now. I just want to know how to structure my schema/data in the postman request.
E.g Input in "education", stored with "Masters:120", "Bachelor:98", "PhD:86" etc -> within the post request:
{
"title" : "Data Analyst",
"desc": "Using both internal and external data sources you will develop insights to identify trends and opportunities whilst highlighting areas or improvement to optimise member interaction. This is a proactive role where you will own how we interpret data, allowing you to provide valuable insight into the development and implementation of product, customer and channel strategies for our sales, retention, and acquisition goals.",
"skills":["SQL" ,"Excel", "Tableau", "PowerBI", "Python", "Azure", "AWS", "ETL"],
"education": ["INPUT AN ARRAY OF EDUCATION AND THEIR VALUES HERE!]
}
Thankyou!

You could modify first your payload into the format of schema.
Payload
const educationData = [
{
degree: 'Masters',
A: 120,
},
{
degree: 'Bachelor',
A: 98,
},
{
degree: 'PhD',
A: 86,
},
{
degree: 'Industry',
A: 99,
},
{
degree: 'Associate',
A: 85,
}
];
Process
const newEducations = educationData.map(education => {
return `${education.degree}:${education.A}`;
});
const storeRole = new RolesPositionSchema({
title: 'Data Analyst',
desc: 'Using both internal and external data sources you will develop insights to identify trends and opportunities whilst highlighting areas or improvement to optimise member interaction. This is a proactive role where you will own how we interpret data, allowing you to provide valuable insight into the development and implementation of product, customer and channel strategies for our sales, retention, and acquisition goals.',
skills: [{Skill value}],
salary: [{Salary value}],
education: newEducations,
popularity: 0,
reccomendations: [{Recommendation value}]
});
After this saved.
Does it that you want?

Related

Getting only needed elements form array in MongoDb Schema

I want to get only those element from notes Array that match the given tag from tags array in notes.
For example : If I want to get only those notes from notes Array having lrn tag in tags array but I am getting either the whole object or only the first matching note.
My Schema :
const mongoose = require('mongoose');
const noteSchema = new mongoose.Schema({
user : {
type: String,
required: true,
unique : true
},
notes : {
type : [{
title : {
type: String,
required: true
},
tags : {
type : [String],
required: true
},
note: {
type: String,
required: true
}
}],
required: true
}
});
const Notebook = mongoose.model('NOTEBOOK', noteSchema);
module.exports = Notebook;
My sample data :
{ _id: ObjectId("621c3a41fa2fe3c07f43edc9"),
user: '620c81434d8a65c1aa36e0d4',
notes:
[ { title: 'Eraning',
tags: [ 'ern', 'lrn', 'dik', 'pik', 'sik' ],
note: 'Prior to his return, Craig worked at NeXT, followed by Apple, and then spent a decade at Ariba, an internet e-commerce pioneer where he held several roles including chief technology officer.\nPrior to his return, Craig worked at NeXT, followed by Apple, and then spent a decade at Ariba, an internet e-commerce pioneer where he held several roles including chief technology officer.\n',
_id: ObjectId("62205a32bab7aed6315195e9") },
{ title: 'Lerningngs',
tags: [ 'lrn', 'eat', 'drink' ],
note: 'Prior to his return, Craig worked at NeXT, followed by Apple, and then spent a decade at Ariba, an internet e-commerce pioneer where he held several roles including chief technology officer.\n',
_id: ObjectId("6220583cbab7aed63151958b") },
{ title: 'Learning',
tags: [ 'learn', 'eran', 'buy', 'sell' ],
note: 'Prior to his return, Craig worked at NeXT, followed by Apple, and then spent a decade at Ariba, an internet e-commerce pioneer where he held several roles including chief technology officer.Solving DSA from Maths.in and SolveMaths.org using great techniques by INDIA and RUSSIA.\n',
_id: ObjectId("6220532dbab7aed631519531") },
{ title: 'Biology',
tags: [ 'tissue', 'cell', 'myto', 'energy', 'glycogen', 'hydrogen' ],
note: 'Prior to his return, Craig worked at NeXT, followed by Apple, and then spent a decade at Ariba, an internet e-commerce pioneer where he held several roles including chief technology officer.Solving DSA from Maths.in and SolveMaths.org using great techniques by INDIA and RUSSIA.\n\n',
_id: ObjectId("621f88d4c189c6b5501c3d5f") },
{ title: 'Chemistry',
tags: [ 'this', 'is', 'great', 'thing', 'to', 'do', 'by', 'time' ],
note: ' Prior to his return, Craig worked at NeXT, followed by Apple, \n and then spent a decade at Ariba, an internet e-commerce pioneer \n where he held several roles including chief technology officer.\n',
_id: ObjectId("621f85e9c189c6b5501c3d49") },
{ title: 'Physics',
tags:
[ 'newtonlawsofmotion',
'ktg',
'thermo',
'fluid',
'mechanice',
'bernaulii' ],
note: 'P\' + hrg + 1/2rv^2 = constant',
_id: ObjectId("621f8520c189c6b5501c3d3f") },
{ title: 'Maths',
tags: [ 'trignometry', 'llp', 'continuity', 'tags', 'circle' ],
note: 'Solving DSA from Maths.in and SolveMaths.org using great techniques by INDIA and RUSSIA.',
_id: ObjectId("621f84d7c189c6b5501c3d37") },
{ title: 'DSA from Net',
tags: [ 'dp', 'stack', 'queue', 'heaps', 'sorting' ],
note: 'Solving DSA from Leetcode.in and GeeksforGeeks.org',
_id: ObjectId("621c3a41fa2fe3c07f43edca") } ],
__v: 7 }
You can use $filter to get documents of given tag as shown below:
Notebook.findOne({
user: "620c81434d8a65c1aa36e0d4" // user ID
},
{
notes: {
$filter: {
input: "$notes",
as: "note",
cond: {
$in: [
"ern", // Tag to search
"$$note.tags"
]
}
}
}
})
Mongo Playground

How Best to Handle Iterating Over Sub-Data in Angular App

In my Angular app with a MongoDB/Node backend, I have been successfully iterating over an array of records and printing them to the view in a table layout - one line per object in the array.
Now I have a situation where I need to break out what was information on one line into three lines, based on info in a "subdata" object. A simplified version of the data looks like this:
data: [
{
name: {
first: "John,
last: "Smith
},
referred: true,
birthDate: date,
city: "New York",
createDate: date,
subdata: {
a: "value a",
b: "value b",
c: "value c"
},
deleted: false
}
]
Rather than iterating once for each object in the "data" array, which I was doing before like this:
<tr *ngFor="let record of records.data | paginate: { id: 'results', itemsPerPage: 12, currentPage: getPageNumber(), totalItems: records.count }">
... I instead need to now print three lines - one for each of the values in the "subdata" object. But each of those lines needs to include the name, the birthDate, and the city that is part of the parent object.
From an architectural point of view, does it make it more sense to create a new backend endpoint, and populate the data in the format I want to iterate over it by (which would involve some repetition of props and values (name, birthDate, city, etc...), like this:
reOrgedData: [
{
name: {
first: "John,
last: "Smith
},
referred: true,
birthDate: date,
city: "New York",
createDate: date,
a: value
deleted: false
},
{
name: {
first: "John,
last: "Smith
},
referred: true,
birthDate: date,
city: "New York",
createDate: date,
b: value
deleted: false
},
{
name: {
first: "John,
last: "Smith
},
referred: true,
birthDate: date,
city: "New York",
createDate: date,
c: value
deleted: false
}
]
or is there a way I can iterate over this in its original data structure, but still break it out into three lines in the view?
My sense is that creating a custom endpoint with the data organized in the form I need is the way to go, even though that does involve some repetition. This approach makes for less hoops-jumping on the front-end. But I am curious for people's take on what would be the best approach in a scenario like this.

Apollo Client replaces an array of objects with the same id and different values with an array of copies of the first object

Our GraphQL server responds to a query with data that includes an array of objects each of which shares the same id and different values for a different key. For instance, we might have an array that looks like:
[
{ id: 123, name: 'foo', type: 'bar', cost: 5 },
{ id: 123, name: 'foo', type: 'bar', cost: 6 },
{ id: 123, name: 'foo', type: 'bar', cost: 7 },
{ id: 123, name: 'foo', type: 'bar', cost: 8 }
]
We can see in the Network tab that the response from the server has the correct data in it. However, by the time it goes through processing by the Apollo Client module the array has been transformed into something that might look like this:
[
{ id: 123, name: 'foo', type: 'bar', cost: 5 },
{ id: 123, name: 'foo', type: 'bar', cost: 5 },
{ id: 123, name: 'foo', type: 'bar', cost: 5 },
{ id: 123, name: 'foo', type: 'bar', cost: 5 }
]
Essentially what we're seeing is that if all of the objects in an array share the same value for id then all objects in the array become copies of the first object in the array.
Is this the intended behavior of Apollo Client? We thought maybe it had something to do with incorrect caching, but we were also wondering if maybe Apollo Client assumed that subsequent array members with the same id were the same object.
It looks like this is behavior as intended. The Apollo Client normalizes on id.
As the other answer suggests this happens because Apollo normalises by ID. There's a very extensive article on the official blog that explains the rationale of it, along with the underlying mechanisms.
In short, as seen by Apollo's cache, your array of objects contains 4 instances of the same Object (id 123). Same ID, same object.
This is a fair assumption on Apollo's side, but not so much in your case.
You have to explicitly tell Apollo that these are indeed 4 different items that should be treated differently.
In the past we used dataIdFromObject, and you can see an example here.
Today, you would use typePolicies and keyfields:
const cache = new InMemoryCache({
typePolicies: {
YourItem: {
// Combine the fields that make your item unique
keyFields: ['id', 'cost'],
}
},
});
Docs
It works for me:
const cache: InMemoryCache = new InMemoryCache({ dataIdFromObject: o => false )};
previous answer solves this problem too!
Also you can change the key name(for example id => itemId) on back-end side and there won't be any issue!
I have the same issue. My solution is to set fetchPolicy: "no-cache" just for this single API so you don't have to change the InMemoryCache.
Note that setting fetchPolicy to network-only is insufficient because it still uses the cache.
fetchPolicy document

How to write this Store structure?

I'm trying to figure out the best way for my Redux Store to handle lists. Right now it looks like this:
Store = {
users: [],
posts: [],
lists: [],
}
My problem with this, is the list array. Essentially it's a store for paginated lists of a specific resource, so for example:
lists: [
{
id: 'users/43/posts',
items: [25, 36, 21]
}
]
Since I am using the url as the id, my component that shows a user's list of posts will know exactly which list to display. Now someone has told me that, this is a very very bad idea. And I just want some advice on what could be better. Another approach suggested was this:
users: [{
id: 2,
posts: [
{
url: 'users/2/posts',
items: [13, 52, 26],
}
]
}]
So what I don't understand, how does Redux know where to save this list? Do I have to specify in the action arguments where to save it?
Thank you for your advice.
Well, technically, anything works if you make it work! The second approach looks more mature, though. You don't want to use URLs as ID. IDs should be numbers or special sequence of characters+numbers. When your application grows, you'll want to normalize your data i.e. store the IDs in a separate array and transform the array of objects into an object with keys as ID.
Example from Normalizr
[{
id: 1,
title: 'Some Article',
author: {
id: 1,
name: 'Dan'
}
}, {
id: 2,
title: 'Other Article',
author: {
id: 1,
name: 'Dan'
}
}]
can be normalized to -
{
result: [1, 2],
entities: {
articles: {
1: {
id: 1,
title: 'Some Article',
author: 1
},
2: {
id: 2,
title: 'Other Article',
author: 1
}
}
}
}
When your application grows, you'll have multiple reducers and sub-reducers. You'll want to slice a specific portion of your state-tree and so on. For that reason someone might have advised you to store your state in a different manner.
But again, anything works if you make it work! Good luck!

defining relationships in Backbone-Relational -- not sure which direction the options are pointing?

I'm having a heckuva time understanding the documentation for Backbone-Relational; it's not 100% clear on which relation to add things like includeInJSON. Probably best to describe my confusion by illustrating the structure I'm trying to create. I have a Venue model that has zero or more nested Address models (1:n relationship). The backend store is MongoDB, which can have embedded objects. I'd like to store it in this format:
{
id: 12345,
label: 'OPUS Cafe Bistro',
addresses: [
{
type: 'mailing',
address1: '#52 - 650 Duncan Ave',
city: 'Penticton, BC'
},
{
type: 'main',
address1: '#106 - 1475 Fairview Rd',
city: 'Penticton, BC'
}
]
}
(Please ignore the ugly data structures; I've adjusted it for brevity.) Now I believe I set up the relationship between Venue and Address thusly:
var Venue = Backbone.RelationalModel.extend({
relations: [
{
type: Backbone.HasMany,
key: 'addresses',
relatedModel: 'Address',
includeInJSON: false,
collectionType: 'Addresses',
reverseRelation: {
key: 'venue'
}
}
});
If I understand correctly, I set includeInJSON to false in order to prevent the Venue from being serialised into the venue key in Address, but under reverseRelation I leave includeInJSON blank in order to have the full Address (without a venue property) serialised as an array in the addresses property of the Venue – as per my hoped-for example. Correct?
By the same token, I'm trying to understand the same concept in relation to a join-style relationship. Consider that Venue now has an organisationID field:
/* venue in JSON format */
{
id: 12345,
organisationID: 336,
label: 'OPUS Cafe Bistro',
addresses: []
}
/* and now for the organisation */
{
id: 336,
label: 'OPUS Entertainment Group'
}
Using the examples in the documentation, which seem to prefer the Backbone.HasMany relationship, I think that I'd have to set up Organisation thus:
var Organisation = Backbone.RelationalModel.extend({
relations: [
{
type: Backbone:HasMany,
key: 'venues',
relatedModel: 'Venue',
includeInJSON: Backbone.Model.prototype.idAttribute,
collectionType: 'Venues',
reverseRelation: {
key: 'organisationID',
includeInJSON: false
}
}
]
});
... which should serialise into the above example, right? (I.e., Venue grabs Organisation's id and inserts it into organisationID, and Organisation doesn't serialise any list of Venues)
Thanks in advance for any help – looking forward to using this handy library, after clawing my eyeballs out trying to write my own relational glue for Backbone.js :-)
(copying my answer from https://github.com/PaulUithol/Backbone-relational/issues/37 over here, so more people can hopefully find it)
I'm sure you've figured it out by now, sorry for replying so late, but just to be sure: options (like collectionType and includeInJSON) apply to the key that's within the same object.
So, for your first example, you could write the relation as:
var Venue = Backbone.RelationalModel.extend({
relations: [
{
type: Backbone.HasMany,
key: 'addresses',
relatedModel: 'Address',
includeInJSON: true,
collectionType: 'Addresses',
reverseRelation: {
key: 'venue',
includeInJSON: 'id'
}
}
});
This will create a Venue that HasMany addresses. The addresses key for any given Venue uses the collectionType Addresses, and is fully serialized because includeInJSON is set to true (not that the default value for includeInJSON is also true; so if you don't specifiy it, it will fully serialize a relation or reverseRelation).
The reverseRelation simply takes the same options, only applies them with respect to the venue key on any Address. In this case, it will only serialize the venue.id property for the venue it's linked to.

Categories