Comparing keys of two Maps - javascript

Im working on an attendance app in React.
I’m pulling all the data successfully and I’m at the point where I’m trying to do attendance tally’s. Each home room earns points for attending classes, but every class consists of a mixture of all of the home rooms.
I have been tracking attendance in a Map, which looks like:
attendance { “StudentOne” => true, “StudentTwo” => true, “StudentThree” => true, “StudentFour” => true, “StudentFive” => true, “StudentSix” => true, }
So imagine I have 3 home rooms, each having two students- 1&2, 3&4, 5&6 (in reality each home room has between 12-20 students).
I’ve also generated a Map for each home room with a list of students.
Is there a way to loop through each attendance record to check which homeroom should be awarded points based on the matching keys in the Map?

Related

How do I create a Google Workspace script to generate a spreadsheet counting users by organizational unit?

The script I'm trying to create sorts the users in my Google Workspace by organizational unit, counts the users in each unit, and generates an output in a spreadsheet that counts the total number of users in each organizational unit.
The code that I'm currently using to sort the users is as follows:
function getDomainUsersList() {
var users = [];
var options = {
domain: 'myworkspace.org', // Google Workspace domain name
customer: 'my_customer',
projection: 'FULL', // Fetch user details
viewType: 'domain_public',
orderBy: 'orgUnitId', // Sort results by organizational unit
};
This is fine for sorting users by organizational unit, but it doesn't do what I want it to do, which is to numerically represent the number of users in each organizational unit. Thanks for your help!

How to filter JSON data based on attributes?

I have the following JSON data.
{
"partners": [
{
"logo": "school-of-bookkeeping.png",
"title": "Schoolofbook<br class='d-none d-md-inline-block'/>keeping.com",
"websiteURL":"https://www.schoolofbookkeeping.com",
"getInTouchURL":"https://www.schoolofbookkeeping.com",
"location":"Santa Monical, CA, US",
"servicesCategories":["Consulting Services","Webgility Setup"],
"accountingSoftware":["QuickBooks Online","QuickBooks Enterprise","QuickBooks Point of Sale"],
"onlineStore":["Magento","Shopify","WooCommerce"],
"marketplace":["Amazon","eBay","Etsy"],
"description": "Teaching Businesses and Accounting Professionals the ins and outs of ecommerce.",
"longDescription":"<p class='fs-16 lh-1-5'>Let's face it; ecommerce is hard. From tracking inventory, sales tax requirements, shipping fulfillment, and general bookkeeping, keeping pace with all the requirements and business workflows is difficult. That's why we have partnered with Webgility to create a learning resource to provide small and medium-sized businesses a seamless and path from setup to implementation, so the accounting is done so that can focus on running your business, rather than your business, rather than running yourself ragged.</p><p class='fs-16 lh-1-5'>Our lifelong learners are here for hire so you can be set up for success and have a trusted advisor to guide you through setup to implementation.</p>",
"servicesWeProvide": "<p class='fs-16 lh-1-5'>Website creation to e-commerce implementation.</p>",
"featured": false,
"partnerType": "Certified",
"link": "school-of-bookkeeping",
"customClass": "school-of-bookkeeping"
},
{
"logo": "danwidth.png",
"title": "Danwidth",
"websiteURL":"https://www.danwidth.com",
"getInTouchURL":"https://completebusinessgroup.com/danwidth/",
"location":"Tucson, AZ, US",
"servicesCategories":["Consulting Services","Webgility Setup"],
"accountingSoftware":["QuickBooks Online","QuickBooks Enterprise","QuickBooks Point of Sale"],
"onlineStore":["Magento","Shopify","WooCommerce"],
"marketplace":["Amazon","eBay","Etsy"],
"description": "Put your ecommerce bookkeeping on cruise control.",
"longDescription":"<p class='fs-16 lh-1-5'>I don't want to be your bookkeeper. I transform businesses through technology by creating automagic workflows that allow your bookkeeping to be handled \"by accident.\" Imagine entering data once, or not at all, and your bookkeeping is done for you. Specializing in brick and mortar retail and ecommerce, I will set up your services to integrate so that your accounting and bookkeeping is done for you as a result of you simply running your business. We work with a host of solution providers that all integrate into your accounting platform that will enable you to make informed business decisions in real-time.</p><p class='fs-16 lh-1-5'>My expertise is unparalleled across all of Intuit's Small business platforms. Online or Desktop, including Point of Sale, if it can be done in QuickBooks, I know how to make it happen. In addition, we partner with other business services to increase your revenue, decrease your expenses, and widen your online presence.</p>",
"servicesWeProvide": "<p class='fs-16 lh-1-5'>End-to-end services from website creation, digital marketing, ecommerce platform to bookkeeping, payroll service setup, and support.</p>",
"featured": false,
"partnerType": "Certified",
"link": "danwidth",
"customClass": ""
}
]
}
How can I filter this on the basis of servicesCategories, accountingSoftware, onlineStore, marketplace, and partnerType?
I want to filter data with $.getJSON() method with on change select box value.
That depends on how you want to go about filtering. There are a few different ways to accomplish this, here is one function that allows you to pass in the key you want to filter on and an array of values to filter by:
let filterBy = (list, keyToFilter, filters) => {
// Allow a string to be passed in
if(!Array.isArray(filters)) filters = [filters];
return list.filter(item => {
let values = item[keyToFilter];
// Check if the filter exists
if(!values) return false;
// For items that aren't arrays, like partnerType
// This makes it compatible with the conditional
// below, where the logic for check happens.
if(!Array.isArray(values)) values = [values];
// Check if array of your filters matches any in list
return filters.some(n => values.includes(n));
}
);
};
Then you can call this on your list like so:
let list = { "partners": [
...
]};
let accountingSoftware = filterBy(list["partners"], "accountingSoftware", ["QuickBooks Online","QuickBooks Enterprise"]);
let partnerType = filterBy(list["partners"], "partnerType", "Certified");
Here is an example if you want to play around with it more, https://repl.it/#BenjaminKnox/filter-json

Objection.js - Realtion with pivot table

i'm having hard times understanding how I should model many-to-many relationships in objections.js.
Basically I have an app with an Users, Games and UsersScore tables. A account can have score in game.
Tables are like this:
USERS TABLE
id
username
GAMES TABLE
id
name
UsersScore TABLE
id
userId
gameId
score
How do I create the relation?
I want to show the logged in user a list of all the games
And if he has score in the game then his score
Thanks!!
This is essentially identical to the requirements outlined at Join table extra properties in the Objection documentation. You could adapt this to create users, games, and users_games tables. Then your User model might look like this:
class User extends Model {
static get relationMappings() {
return {
relation: Model.ManyToManyRelation,
modelClass: Game,
join: {
from: 'users.id',
through: {
from: 'users_games.user_id',
to: 'users_games.game_id',
extra: ['score']
},
to: 'game.id'
}
};
}
}
Here you can see that we've added an extra score column to our users_games join table. Then I imagine you would get a list of games with something like:
const user = await User.query().findOne({ username: 'wombatsarefluffy' });
const games = await user.$relatedQuery('games');
See the documentation page for an example of how to construct the migrations.

Firebase Query for Products in Categories (database setup and best practice)

TL;DR
products have multiple categories.
View should show only all subcategories and products that have the category assigned.
How to setup the DB and queries?
I'm learning Vue and Firebase at the moment coming from a C# and SQL background, I need some help and advice on the noSQL side of things.
EDIT: categories and products are two separate collections (at the moment).
I have products, which can have multiple categories (see product 5)
products: {
prod1-id: {
name:'apple-type-A',
price: 2
cats: cat1-id
}
prod2-id: {
name:'apple-type-B',
price: 2.5
cats: cat1-id
}
prod3-id: {
name:'banana-type-A',
price: 1.6
cats: cat2-id
}
prod4-id: {
name:'banana-type-B',
price: 1.9
cats: cat2-id
}
prod5-id: {
name:'smoothie',
price: 5,
cats: [cat2-id, subCat1-id, subCat2-id]
}
}
Those categories are a tree.
categories: {
cat1-id: {
name: 'fruits',
subCat1-id: {
name: 'apple'
}
subCat2-id: {
name: 'banana'
}
},
cat2-id: {
name: 'MySmooth'
}
}
The customer should see the first tree.
The landing page should only show the first depth of the category tree and every product without a category (maybe add a category called 'no category').
When you click on a category is should show all the subcategories and products, that have this category.
This goes on until the deepest branch.
I tried to sketch my idea:
VIEW
For programming I use Vue, with vuex and vuexfire and as framework Vuetify.
I have the complete product management setup but I don't know how to query for this view.
My idea was to reuse a <v-card v-for="p of products"> I already have and is working fine.
But this shows only products, not categories. How do I get the categories into the mix?
QUERY
Working with vuexfire this is quite simple.
bindSoldProducts: firestoreAction(({ bindFirestoreRef }) => bindFirestoreRef('products', productsColl.where('isSold', '==', true))
but how can I get the categories and products now show side by side?
I've started to get the products together by querying, but have no idea how to put the categories into the mix:
firebase.firestore.collection('products').orderBy('name', 'asc').onSnapshot(snap => {
const productsArray: any = []
snap.forEach(doc => {
const product = doc.data()
product.id = doc.id
productsArray.push(product)
})
store.commit('setAllProducts', productsArray)
})
Do I need to structure my database differently?
Do I just query the products and use "some js logic/magic" to show the categories? But how would I then get the views.
Are the collection group queries of firebase the right way to go? If yes, how?
Please advice
Try a for in all Categories and get the fruits:
const categories = {
"cat1-id": []
}
Object.keys(categories).forEach(cat => {
const res = db.collection('products').where('cats', 'array-contains', cat).get()
// Resolve and put (push) in categories[cat]
})
See: https://firebase.google.com/docs/firestore/query-data/queries
I'm writing my response an answer as it was too long for a comment.
If I understood your use case correctly, you want to have a DB structure where you have a list of products and their respective categories which both will be displayed simultaneously side by side on your Vue application view.
While I'm not a Vue expert, I can suggest using the following structure for your Cloud Firestore database: Products/{product}/categories/{category}, which translates to collection/{document}/collection/{document}.
In the Cloud Firestore data model you can have a collection within another collection, and this is called a subcollection. For example, you could have Products/fruits/Categories/banana and inside the banana document you could have type, price, or id fields among many others.
Then, you could use Collection group queries to retrieve documents from a collection group instead of from a single collection. A collection group consists of all collections with the same ID. By default, queries retrieve results from a single collection in your database.
For example, you could create a categories collection group by adding a Categories subcollection to each product and then retrieve results from every product's categories subcollection at once, let's say bananas:
const querySnapshot = await db.collectionGroup('categories').where('productName', '==', 'banana').get();
querySnapshot.forEach((doc) => {
console.log(doc.id, ' => ', doc.data());
// Banana from Mexico, Banana from Honduras, etc.
});
Before using a collection group query, do not forget to create an index that supports your collection group query. You can create an index through an error message, the console, or the Firebase CLI.

AngularFire2 with Firebase Realtime DB - Nested Data Query Angular 6 [duplicate]

The structure of the table is:
chats
--> randomId
-->--> participants
-->-->--> 0: 'name1'
-->-->--> 1: 'name2'
-->--> chatItems
etc
What I am trying to do is query the chats table to find all the chats that hold a participant by a passed in username string.
Here is what I have so far:
subscribeChats(username: string) {
return this.af.database.list('chats', {
query: {
orderByChild: 'participants',
equalTo: username, // How to check if participants contain username
}
});
}
Your current data structure is great to look up the participants of a specific chat. It is however not a very good structure for looking up the inverse: the chats that a user participates in.
A few problems here:
you're storing a set as an array
you can only index on fixed paths
Set vs array
A chat can have multiple participants, so you modelled this as an array. But this actually is not the ideal data structure. Likely each participant can only be in the chat once. But by using an array, I could have:
participants: ["puf", "puf"]
That is clearly not what you have in mind, but the data structure allows it. You can try to secure this in code and security rules, but it would be easier if you start with a data structure that implicitly matches your model better.
My rule of thumb: if you find yourself writing array.contains(), you should be using a set.
A set is a structure where each child can be present at most once, so it naturally protects against duplicates. In Firebase you'd model a set as:
participants: {
"puf": true
}
The true here is really just a dummy value: the important thing is that we've moved the name to the key. Now if I'd try to join this chat again, it would be a noop:
participants: {
"puf": true
}
And when you'd join:
participants: {
"john": true,
"puf": true
}
This is the most direct representation of your requirement: a collection that can only contain each participant once.
You can only index known properties
With the above structure, you could query for chats that you are in with:
ref.child("chats").orderByChild("participants/john").equalTo(true)
The problem is that this requires you to define an index on `participants/john":
{
"rules": {
"chats": {
"$chatid": {
"participants": {
".indexOn": ["john", "puf"]
}
}
}
}
}
This will work and perform great. But now each time someone new joins the chat app, you'll need to add another index. That's clearly not a scaleable model. We'll need to change our data structure to allow the query you want.
Invert the index - pull categories up, flattening the tree
Second rule of thumb: model your data to reflect what you show in your app.
Since you are looking to show a list of chat rooms for a user, store the chat rooms for each user:
userChatrooms: {
john: {
chatRoom1: true,
chatRoom2: true
},
puf: {
chatRoom1: true,
chatRoom3: true
}
}
Now you can simply determine your list of chat rooms with:
ref.child("userChatrooms").child("john")
And then loop over the keys to get each room.
You'll like have two relevant lists in your app:
the list of chat rooms for a specific user
the list of participants in a specific chat room
In that case you'll also have both lists in the database.
chatroomUsers
chatroom1
user1: true
user2: true
chatroom2
user1: true
user3: true
userChatrooms
user1:
chatroom1: true
chatroom2: true
user2:
chatroom1: true
user2:
chatroom2: true
I've pulled both lists to the top-level of the tree, since Firebase recommends against nesting data.
Having both lists is completely normal in NoSQL solutions. In the example above we'd refer to userChatrooms as the inverted index of chatroomsUsers.
Cloud Firestore
This is one of the cases where Cloud Firestore has better support for this type of query. Its array-contains operator allows filter documents that have a certain value in an array, while arrayRemove allows you to treat an array as a set. For more on this, see Better Arrays in Cloud Firestore.

Categories

Resources