How to convert SQL Database to Mongodb? - sql

I am having a bit of trouble with what the best schema would be in mongo for some golf data that I have.
Tables:
ClubManufacturer (id, name, descr) -- ex: 1, Titleist
ClubType (id, name) -- ex: 1, Driver
Club (id, id_clubType, id_clubManufacturer, name, url) -- ex: 1, 1, 1, 913D2, link
Should I just store each club manufacturer as a document with club (and type) as properties of the document? I am at a loss because I'll be needing to access the data such that I need to show, all Drivers, or, all clubs by manufacturer.
I am also new to mongodb so any insight is much appreciated.
Thanks!

If your manufacturers have large descriptions then you might want to keep them separate to reduce the redundancy. As an extension of Asya Kamsky's answer:
Manufacturer Collection:
{
_id: "Manufacturer Name",
description: "Long ... Description"
}
Club Collection:
{
_id: Auto_Generated_Hash,
manufacturer: "Name/ID",
type: "Driver",
name: "Club Name",
url: "http://www.url.com/"
}
I used the manufacturer's name as the _id so that if you don't need the description you still know what the manufacturer is without doing a "join".

Unless your Manufacturer and Type tables are actually much larger than what you listed here, it seems simple to just have each document in Club collection look something like:
{ _id: 1,
manufacturer: 'Titleist',
type: 'Driver',
name: '913D2',
url: 'http://blah.blah.blah/'
}
Now you can index manufacturer and type fields to support fast queries by either of the attributes.

Related

Creating a shop/ item system in flutter with SQL, how to structure in-game/app items properly?

New to SQL & databases, creating an in-app shop that holds different items.
void _createTableItems(Batch batch) {
batch.execute('DROP TABLE IF EXISTS Items');
batch.execute('''CREATE TABLE boughtItems (
id INTEGER PRIMARY KEY,
price INTEGER
)''');
}
class Item {
Item({required this.id, required this.price, required this.title});
String title;
int id;
int price;
}
List<Item> availableProducts = [WeaponItem(id: 0, strength: 5), WeaponItem(id: 1, strength: 7), StableItem(id: 2, speed: 4), FoodItem(id: 3, rev: 7)]
I pretty much have the most basic strucutre possible right now.
When I need to get the products, all I do is search the availableProducts list of items for ID's in the database query.
Future<List<Item>> getBought() async {
await database;
List products = await _database!.query("Items");
List<Item> result = [];
for (var element in products) {
result.add(availableProducts.where((e) => e.id == element["id"]).first);
}
return result;
}
Is this an acceptable way to do this?
What I'm worried about is the mixing of item types.
I'm a bit lost since there's multiple things I could do. Should I create a different table holding all the properties of each individual items? Should I add a type string to the table to differentiate the different items?
I would create one table for example products. This table
has general information about the products(id, name, product_number, info) that all products have in common. If you want additional and different information for every product type, I would add a fk_type which references to a product_type(id, name) table that stores the different product types. Then I would create an additional table for every product type. Ex: product_weapon(id, size, ammunition, reload_time ), product_chair(id, high, depth, weight). But you can also work just with the simple product table and add general description fields that could store jsons, xmls, css files.

Merging columns and jsonb object array into a single jsonb column

I have a table visitors(id, email, first_seen, sessions, etc.)
and another table trackings(id, visitor_id, field, value) that stores custom, user supplied data.
I want to query these and merge the visitor data columns and the trackings into a single column called data
For example, say I have two trackings
(id: 3, visitor_id: 1, field: "orders_made", value: 2)
(id: 4, visitor_id: 1, field: "city", value: 'new york')
and a visitor
(id: 1, email: 'hello#gmail.com, sessions: 5)
I want the result to be on the form of
(id: 1, data: {email: 'hello#gmail.com', sessions: 5, orders_made: 2, city: 'new york'})
What's the best way to accomplish this using Postgres 9.4?
I'll start by saying trackings is a bad idea. If you don't have many things to track, just store json instead; that's what it's made for. If you have a lot of things to track, you'll become very unhappy with the performance of trackings over time.
First you need a json object from trackings:
-- WARNING: Behavior of this with duplicate field names is undefined!
SELECT json_object(array_agg(field), array_agg(value)) FROM trackings WHERE ...
Getting json for visitors is relatively easy:
SELECT row_to_json(email, sessions) FROM visitors WHERE ...;
I recommend you do not just squash all those together. What happens if you have a field called email? Instead:
SELECT row_to_json((SELECT
(
SELECT row_to_json(email, sessions) FROM visitors WHERE ...
) AS visitor
, (
SELECT json_object(array_agg(field), array_agg(value)) FROM trackings WHERE ...
) AS trackings
));

'Tagging' records based on dynamic attributes, and filters from another table

I have an a Groups table with an array of JSON objects representing different filters to be applied to a SQL query
Example group:
id: 1,
name: "my group",
filters: [
{field: "sessions", type: "greater_than", value: 5},
{field: "email", type: "contains", value: "#example.com}
]
An example record of the filtered table Visitors
id: 1, email: "example#gmail.com", sessions: 5, more_meta_data..
What I'd like to get is something like:
id: 1, matching_groups: ["my group"], email: "example#gmail.com", sessions: 5 more_meta_data..
Note that a visitor can be in many groups at the same time.
When querying a Visitor, I'd like to append the name of all the Groups for which all the filters match the attributes on the Visitior record.
I am kind of lost on this one, and apologise if I haven't explained it clearly enough. Does Postgres allow for this to be done at the DB level?
Any help is much appreciated, thanks

ElasticSearch: Query_String but must match 1 of the terms in a specific field?

I want to build an ElasticSearch query where I query multiple fields, but one of the words in the query MUST match one of the fields.
For instance, suppose I query for "holiday party food", I want it to return all documents that have at least 1 of the terms in the title, and the rest in the html_source.
If a document has:
title: Holiday, html_source: party food => MATCH
title: Party, html_source: food holiday => MATCH
title: Food, html_source: holiday party => MATCH
title: RANDOM TITLE, html_source: holiday party food => NO MATCH.
This is what I have constructed so far, and it matches documents that have all the terms in the html_source, but NOT in the title, which is not what I want.
{
"query":{
"query_string":{
"query":"holiday party food",
"default_operator":"AND",
"fields":[
"title","html_source"
]
}
},
"sort":[
{
"total_shares":"desc"
}
]
}
Here is a query syntax version that I think will do want you want:
+(
(+title:holiday +(body:party body:food -body:holiday))
(+title:party +(body:holiday body:food -body:party)
(+title:food +(body:holiday body:party -body:food))
)
If this does not work, I think it points you in the right direction. The trick in this kind of query is to enumerate all of the choices explicitly.

add items to cart Rails

Let's say customer is adding multiple products to cart.
Add car, apartment, tour, some coupons.
Products belong to categories.
Category has name attribute.
But how to give different attributes to car, apartment, tour, coupon?
I can't definitely create everything from product model.
So should I create different models for each category and connect through has many ro products model?
Or am I going to wrong direction?
Thanks
Having a Category for individual product seems to be a good approach here. Since your Category differs according to attributes. What you can do is create One more model, let's say: MasterCategory which has many Category and Category belongs to MasterCategory, which means for your MasterCategory Cars you'll have Audi, BMW, Nissan etc etc. categories and then link your products to their respective vendors in a table products_categories which will have product_id, category_id.
In my opinion, schema could go like this:
ProductsCategory:
product_id, category_id
MasterCategory:
id, name, created_at, updated_at
Category:
id, master_category_id, parent_id, name, position, name, permalink
For e.g. - A car MasterCategory will look like this:
#<MasterCategory id: 1, name: "cars", created_at: "2012-02-14 13:03:45", updated_at: "2012-02-14 13:03:45">
and its categories will be:
[#<Category id: 1, master_category_id: 1, parent_id: nil, position: 0, name: "cars", created_at: "2012-02-14 13:03:45", updated_at: "2012-02-14 13:03:45", permalink: "cars">, #<Category id: 2, master_category_id: 1, parent_id: 1, position: 0, name: "Audi", created_at: "2012-02-14 13:03:45", updated_at: "2012-02-14 13:32:51", permalink: "cars/audi">]
Now you can have two methods parent and children in your Category Model using parent_id attribute to locate and traverse master and sub categories easily. And you can use permalink attribute to easily locate a category which is under another category with one query: Category.find_by_permalink(params[:permalink]) and can display all the products related with this particular category. In future when you'll scale, I can bet you, you'll require this position attribute to manage position of your categories to display on your page. And in last master_category_id will give you an ease in life with:
car = MasterCategory.find(1)
car.categories.where("parent_id IS NOT NULL")
All the best!! :)