Querying grandchild properties in Firebase - rest

I try to come up with a Firebase realtime DB structure for an online store.
The store should have a collection of products, each product can belong to one or more categories. Is it possible to construct a query to get all products in the computers category with a single HTTP request (assuming I use Firebase REST API)? Here is a sample piece of data:
{
"products": {
"-KaXxv2xD9WaIqHMsHYM": {
"title": "Item 1",
"categories": {
"electronics": true,
"computers": true
}
},
"-KaXyvdw5gmuBmGi5unb": {
"title": "Item 2",
"categories": {
"electronics": true
}
},
"-KaXyyyzmP9Y6askhLdx": {
"title": "Item 3",
"categories": {
"computers": true
}
}
}
}
I was also trying to use arrays for categories but looks like arrays support is very limited in Firebase and they should be avoided.
UPDATE:
This query works:
GET /products.json?orderBy="categories/computers"&equalTo=true
But it requires an index for every single category:
{
"rules": {
"products": {
".indexOn": ["categories/computers", "categories/electronics"]
}
}
}

You should have an additional categories node which have products list. That would make easier and efficient access to products for a specific category.
Similar aproach is used at Firebse sample. See code
childUpdates.put("/posts/" + key, postValues);
childUpdates.put("/user-posts/" + userId + "/" + key, postValues);
They have save same data at posts and user-posts nodes.

Related

DynamoDB PartiQL Query For Specific Map Element From List

I have a DynamoDB with data that looks like this:
{
"userId": {
"S": "someuserID"
},
"listOfMaps": {
"L": [
{
"M": {
"neededVal": {
"S": "ThisIsNeeded1"
},
"id": {
"S": "1"
}
}
},
{
"M": {
"neededVal": {
"S": "ThisIsNeeded2"
},
"id": {
"S": "2"
}
}
},
...
]
},
"userName": {
"S": "someuserName"
}
}
The listOfMaps can contain more than just 2 maps, as is denoted by the ellipsis. Is there a PartiQL query I can put together that will let me get the neededVal based on the userId and the id of the item in the map itself?
I know that I can query for the n-th item's neededVal like this:
SELECT "listOfMaps"[N]."neededVal"
FROM "table-name"
WHERE "userId" = 'someuserID'
But is it possible to make it do something like this:
SELECT "listOfMaps"."neededVal"
FROM "table-name"
WHERE "userId" = 'someuserID' AND "listOfMaps"."id" = '4'
It looks like you're modeling the one-to-many relationship using a complex attribute (e.g. a list of objects). This is a completely valid approach to modeling one-to-many relationships and is best used when 1) the results data doesn't change (or don't change often) and 2) you don't have any access patterns around the data within the complex attribute.
However, since you do want to perform searches based on data within the complex attribute, you'd be better off modeling the data differently.
For example, you might consider modeling results in the user partition with a PK=user_id SK=neededVal#. This would allow you to fetch items by User ID (QUERY where PK=USER#user_id SK begins_with neededVal#).
I don't know the specifics around your access patterns, but can say that you'll need to move results into their own items if you want to support access patterns around the data within your complex attribute.

mongo db how to store multi relation like graph

I have to store some users and their group relations like below
So I am planning to create a collection like below
UserGroupRelation Collections
{
"user":String,
"Group":String"
}
example of collections for Super admin users
{
"user":"Adminuser-1",
"Group":"Group1"
}
{
"user":"Adminuser-1",
"Group":"Group2"
}
{
"user":"Adminuser-1",
"Group":"Group3"
}
where user & Group column is indexed and I will run below kind of query
1.Whenever I want to check whether given user has access to the given group
db.UserGroupRelation.find( { user: "Adminuser-1", Group: "Group2" })
2.Also I want to delete all the association whenever we delete group
db.UserGroupRelation.deleteMany({ Group: "Group2" })
3.Also find all the users of a group
db.UserGroupRelation.find( { Group: "Group2" })
4.Find Hierarchy?, with my Approach I am not able to find
But with this approach I am duplicating lot of data also in real time I may have 10000 groups and 1 million user so there would be performance issue. And with this I am not able to maintain a hierarchy like SuperAdmin->SubAdmin->user of same group
I checked with mongo tree but it is not fitting to this requirement. is there a better way to handle this requirement in mongodb .?
This is the structure your graphic requirements show. It does still lead to repetition though so you will need to change it. Read up on one-many relationships.
{
"superAdmin_ID": "001",
"groups": [
{
"_id": "0",
"groupNumber": "1",
"users": [
{
"_userKey": "1023"
"userName": "Fred"
},
{
"_userKey": "1024"
"userName": "Steve"
}
],
"subAdmin": {
"_adminKey": "55230"
"adminName": "Maverick"
},
},
{
"_id": "1",
"groupNumber": "2",
"users": [
{
"_userKey": "1023"
"userName": "Fred"
},
{
"_userKey": "4026"
"userName": "Ella"
}
],
"subAdmin": {
"_adminKey": "55230"
"adminName": "Maverick"
},
},
{
"_id": "2",
"groupNumber": "3",
"users": [
{
"_userKey": "7026"
"userName": "James"
}
],
"subAdmin": {
"_adminKey": "77780"
"adminName": "Chloe"
},
},
]
}
You can also make subAdmin an array if you need more than one subAdmin within a group.

Where filter with HasAndBelongsToMany relation in Loopback

first of all I am sorry if this has been asked 1st, I searched for this and got few links but wasn't helpful.
I am working on simple chat application created in Angular 4 which has Customer entity and Conversation entity and Message. In The customer => hasAndBelongsToMany => Conversation with MongoDb Connector.
In customer.json
"relations": {
"conversations": {
"type": "hasAndBelongsToMany",
"model": "Conversation"
}
}
In conversation.json
"relations": {
"customers": {
"type": "hasAndBelongsToMany",
"model": "Customer"
}
}
This creates table customerconversation which contains conversationId and customerId
Now basically I want to find conversation for two customer Ids, So I tried following filters but it doesn't seem to work and always returns empty array even though there is conversation having these two customer ids.
let filter = {
where: {
and: [
{
customers: {
inq: [
this.customerId // = 59bb981f35fcc941e8ba64e4
]
}
},
{
customers: {
inq: [
this.authService.getCurrentId() // = 59bb98c735fcc941e8ba68ff
]
}
}
]
}
};
and another without and operator
let filter = {
where: {
customers: {
inq: [
this.customerId, // 59bb981f35fcc941e8ba64e4
this.authService.getCurrentId() // 59bb98c735fcc941e8ba68ff
]
}
}
};
These both returns customer with mentioned Id but with 0 conversations. I know I can get all conversations of specific customer by using include filter for conversations but still those would need to be filtered as I want single conversation of this customer with another specific customer.
You can get the information by grabbing the customer first and then using the relations and include to get the data you need.
Example is based on the assumption that you are writing this using typescript & loopback-sdk-builder on an angular application.
this.customerApi
.getConversations(this.authService.getCurrentId(), {
where: {
customerId: this.customerId
})
.subscribe(result => {
// your logic here
})

Meteor. Sorting my collection by a deeply nested value

In my application I have a list of tiles representing each project in a portfolio. This is the main list view for the app and all projects are fetched from the collection without any sorting or ordering.
When I have an optional slug parameter specified in my route (for the category assigned to the project) I want to be able to display the projects within the UI that match that category first, and then display the other ones that don't match the category.
For reference, I have included the code for the route below:
/**
* Project list view (all projects) with optional
* filter parameter for showing projects only by
* their category name.
*/
this.route('list', {
path: '/:_category_slug?',
template: 'template_main',
action: function() {
if(this.ready()) {
this.render();
}
},
waitOn: function() {
return [
Meteor.subscribe('projects'),
Meteor.subscribe('formations'),
Meteor.subscribe('categories')
];
},
data: function() {
if(this.params._category_slug) {
/**
* Building up the query given the category slug and the language
*/
var query = {};
query['slug.' + App.language] = this.params._category_slug;
/**
* Grab the category given the query, so we can get its 'id'
*/
var category = App.models.categories.findOne(query);
/**
* This is the query I need to work on so that I can achieve what I want
*/
return App.models.projects.find({}).fetch();
}
else {
return App.models.projects.find({}).fetch();
}
},
yieldTemplates: {
'components_header': {to: 'header'},
'views_list': {to: 'content'},
'components_footer': {to: 'footer'}
}
});
For reference, I have also included a sample of the data for three projects that is relevant to this question.
{
"id": 10,
"slug": {
"en": "sample-english-slug",
},
"title": {
"en": "Sample English Title",
},
"description": {
"en": "A good description.",
},
"category_ids": [
{
"id": 5
},
{
"id": 6
}
],
},
{
"id": 12,
"slug": {
"en": "another-sample-slug",
},
"title": {
"en": "Another sample title",
},
"description": {
"en": "Sample description three",
},
"category_ids": [
{
"id": 1
},
{
"id": 4
}
],
},
{
"id": 11,
"slug": {
"en": "another-sample-slug",
},
"title": {
"en": "A sample title",
},
"description": {
"en": "Sample description",
},
"category_ids": [
{
"id": 2
},
{
"id": 5
}
],
}
So what I would want to do is make sure that given a category with an ID of 5, I want those first two projects to be the first two that appear.
Can this be done in meteor, without having to resort to writing extra logic in JS? One approach I did have once was to update each project from within the Client side collection (something I no longer do) and set a few extra attributes, then sort after that.
When dealing with syncing client and server collections, this is not really feasible.
From the mongodb docs:
Use the dot notation to match by specific fields in an embedded document. Equality matches for specific fields in an embedded document will select documents in the collection where the embedded document contains the specified fields with the specified values. The embedded document can contain additional fields.
I don't know if you can do it with a single query, but you can concat two complementary queries that use dot notation.
var selected = App.models.projects.find({'category_ids.id': category._id}).fetch();
var other = App.models.projects.find({'category_ids.id': {$ne: category._id}}).fetch();
return selected.concat(other);

Sorting by document values in couchbase and scala

I am using couchbase and I have a document (product) that looks like:
{
"id": "5fe281c3-81b6-4eb5-96a1-331ff3b37c2c",
"defaultName": "default name",
"defaultDescription": "default description",
"references": {
"configuratorId": "1",
"seekId": "1",
"hsId": "1",
"fpId": "1"
},
"tenantProducts": {
"2": {
"adminRank": 1,
"systemRank": 15,
"categories": [
"3"
]
}
},
"docType": "product"
}
I wish to get all products (this json is product) that belong to certain category, So i've created the following view:
function (doc, meta) {
if(doc.docType == "product")
{
for (var tenant in doc.tenantProducts) {
var categories = doc.tenantProducts[tenant].categories
// emit(categories, doc);
for(i=0;i<categories.length;i++)
{
emit([tenant, categories[i]], doc);
}
}
}
}
So i can run the view with keys like:
[["tenantId", "Category1"]] //Can also have: [["tenant1", "Category1"],["tenant1", "Category2"] ]
My problem is that i receive the document, but i wish to sort the documents by their admin rank and system rank, these are 2 fields that exists in the "value".
I understand that the only solution would be to add those fields to my key, determine that my key would be from now:
[["tenantId", "Category1", "systemRank", "adminRank"]]
And after i get documents, i need to sort by the 3rd and 4th parameters of the key ?
I just want to make sure i understand this right.
Thanks