Is Wildcard Functionality Possible in Firestore Queries? - firebase

I'm trying to decide how to model data in firestore.
Basically, it's for an app that lists happy hours and other specials that restaurants have. Each restaurant/bar could have multiple specials and happy hours depending on the day of the week.
This is a very simplified example of how I was hoping to model the data:
name: "Margaritaville",
geo: {
latitude: 42,
longitude: -105
},
offers {
0: {Type: Happy Hours, Time: 3p-6p, Mon: 1, Tue: 1, Wed: 1, Thu: 1, Fri: 0, Sat: 0, Sun: 0 },
1: {Type: Happy Hours, Time: 2p-5p, Mon: 0, Tue: 0, Wed: 0, Thu: 0, Fri: 1, Sat: 1, Sun: 0},
2: {Type: Happy Hours, Time: All Day, Mon: 0, Tue: 0, Wed: 0, Thu: 0, Fri: 0, Sat: 0, Sun: 1},
3: {Type: Brunch Special, Time: 11a-2p, Mon: 0, Tue: 0, Wed: 0, Thu: 0, Fri: 0, Sat: 0, Sun: 1}
},
etc: "foo",
etc: "bar"
I WANTED to store all the offers data as a nested object inside each business document rather than as a separate collection, as most of the queries will require most of this information along with the lat/long, photos, name, etc. But...
I ultimately want to be able to do query filters by day of the week (Mon, Tue, etc) and offer times and offer types (Happy Hours, Brunch) and distance from user, etc. The way the info is modeled now however, the "offers" that are created inside each document, are ordered (0, 1, 2 etc), so if I wanted to perform a query of all restaurants within 10 miles that have happy hour specials on Monday, for example, I was hoping to do something like this:
db.collection("restaurants").where("offers.WILDCARD.days.Mon", "==", 1)
Note, the "WILDCARD" above. Is there any way to make this work, or do I have to move offers to a separate collection or subcollection? I've been trying to wrap my head around de-normalization, I've only ever worked with SQL databases, so I'm open to advice with regard to how I should be thinking about this.

Firestore doesn't support any wildcards in queries. Furthermore, if your "offers" field is an array, you won't be able to query any of its nested object contents.
What you should do instead is break out "offers" into a subcollection, with each of its elements being a new document in that subcollection. You can query the subcollection for matches against the document properties. If you find a match, then you can do a second get() to find the parent document if needed.

Related

How Do I Specify Read and Write Capacity Units for AWS Amplify Tables So I Can Move Away From On-Demand Tables?

Problem:
The AWS Amplify CLI does not offer options to move away from "on-demand" usage, to provisioned for DynamoDB tables. Thus, I would like to specify this information in the CloudFormation stack.
What is the best practise for this? I would like to sustain the changes written as infrastructure as code for future deployments.
Here are the steps:
Go to your amplify/backend/api/[projectName]/parameters.json folder
Find the DynamoDBBillingMode and change it to "PAY_PER_REQUEST"
Add "DynamoDBModelTableReadIOPS": 1, below DynamoDBBillingMode to set the reads for all tables
Add "DynamoDBModelTableWriteIOPS": 1, below DynamoDBModelTableReadIOPS to set the writes for all tables
These three key/value pairs should be in the route table.
Final JSON:
{
"AppSyncApiName": "name",
"DynamoDBBillingMode": "PROVISIONED",
"DynamoDBModelTableReadIOPS": 1,
"DynamoDBModelTableWriteIOPS": 1,
...
}
How To Customise Reads and Writes Per Table:
Create an override.ts file in the same folder as your parameters.json file
Specify your billing mode like this example: resources.models["Contact"].modelDDBTable.billingMode = "PROVISIONED";
Specify your read and write capacity units like this example: resources.models["Contact"].modelDDBTable.provisionedThroughput = { "readCapacityUnits": 1, "writeCapacityUnits": 1 };
Final JSON:
{
resources.models["Contact"].modelDDBTable.billingMode = "PROVISIONED";
resources.models["Contact"].modelDDBTable.provisionedThroughput = { "readCapacityUnits": 1, "writeCapacityUnits": 1 };
}

Is EXDATE not included in rrule for Full Calendar

I have a recurring calendar event that happens on the 4th Friday of every month and I want to exclude 1 Friday event. I've tried EXDATE but I'm getting an error
Failure passing JSON
Without EXDATE the rrule works fine.
Here are the details that I'm using in Full Calendar to produce the event
{
start: "2019-07-06T09:00:00+10:00",
end: "2019-07-06T15:00:00+10:00",
rrule: "FREQ=WEEKLY;DTSTART=20190607T090000;EXDATE=20190705T090000;INTERVAL=4;BYDAY=FR",
title: "Weed Spraying",
description: "June, Harry, Pat, George, Valda, Helen, Karen, Ken",
color: "red",
url: "./?action=detail_view&id=22",
duration: "06:00"
}
OK I worked it out, #Arnaud is right, RRULE, EXDATE and DTSTART are properties not parameters of rrule, BUT they do go in the rrule property for FullCalendar with a \n newline, they also require a : NOT =. Example
rrule: 'DTSTART:20190308T120000Z\nRRULE:FREQ=WEEKLY;UNTIL=20220330\nEXDATE:20190614T120000Z\nEXDATE:20190628T120000Z'
Notice how there are 2 EXDATE properties, for each date you want to exclude, you need to put an EXDATE.
I spent 3 days trying to get this to work, hopefully this will help save someone else time.
It is possible to add exceptions. You just need to format the RRule string correct:
DTSTART:20190610T103000\nRRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20190801\nEXDATE:20190618T103000Z\nEXDATE:20190619T103000
Watch this code sandbox for a demo
This format can also be used for multiple EXDATE:
rrule: "DTSTART:20201114T000000Z\nRRULE:FREQ=WEEKLY\nEXDATE:20201121T000000Z,20201128T000000Z"
This string was formatted using rruleSet.exdate(new Date(Date.UTC(2012, 5, 1, 10, 30))) from rrule.js library to add multiple EXDATE in the rrule object then using the method .toString()
Also, note that adding the 'Z' char for RRule datetimes now works in v5.4.0
Do not know much about this particular JSON format but the EXDATE is a property, not a parameter of RRULE.
Please try
rrule: "FREQ=WEEKLY;DTSTART=20190607T090000;INTERVAL=4;BYDAY=FR\nEXDATE=20190705T090000"
In the latest version 5.4.0 the following code will work:
DTSTART:20201101T040000Z
RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TU
EXDATE:20201110T040000Z,20201124T040000Z
FullCalendar now supports multiple exdate
I used the RRule and RRuleSet to produce the rrule string:
*NOTE: You will have to be careful with daylight savings. That's why I had to adjust a couple of times. Do not focus on my specific date object. This is just an example of the solution to support multiple exdates using RRuleSet and RRule.
const rruleSet = new RRuleSet();
rruleSet.rrule(new RRule({
freq: Frequency.WEEKLY,
interval: 1,
byweekday: [RRule.TU],
dtstart: new Date(2020, 10, 1, 0, 0, 0, 0)
}));
rruleSet.exdate(new Date(2020, 10, 9, 23, 0, 0, 0));
rruleSet.exdate(new Date(2020, 10, 23, 23, 0, 0, 0));
console.log(rruleSet.toString());
Here is the issue number:
https://github.com/fullcalendar/fullcalendar/issues/5726

How to apply if statement to calcuate integer value inside a group question in Enketo(KoboToolbox)?

I am building a survey form through KoboToolbox. The web forms are Enketo based. I have some questions of the following type (before comma is first column and first row is data titles in XLSform format):
type, name
begin_group, group_farmexpenses_q5
note, group_farmexpenses_q5_note
integer, group_farmexpenses_q5_p1
text, group_farmexpenses_q5_column_1
end_group,
begin_group, group_farmexpenses_q5_1
note, group_farmexpenses_q5_1_note
integer, group_farmexpenses_q5_1_p1
text, group_farmexpenses_q5_1_column_1
end_group,
What i want to do is apply if statement for the integer values inside these two groups, however I get error. Here is what I do to apply if-statement :
if(${group_farmexpenses_q5_p1}=999, 0, ${group_farmexpenses_q5_p1})
if(${group_farmexpenses_q5_1_p1}=999, 0, ${group_farmexpenses_q5_1_p1})
since the above are calculate statements and each one is referred to as "expense1" and "expense2"
i then just add them
${expense1} + ${expense2}
I get error message:
if({group_farmexpenses_q5_1_p1} = 999, 0,
/model/instance[1]/data/group_wx0mk24/group_farmexpenses_q5_1/group_farmexpenses_q5_1_p1
), message: The expression is not a legal expression. (line:
undefined, character: undefined)
Any ideas how to fix this? I think there should be an easy fix but I don't know much about XLSform structures.
Proposed solution through online search for #Ziaw. Instead of first conditioning and then adding, both can be done in one step:
calculated data field compute this
if(${fexp_q1} = 999, 0, ${fexp_q1}) + if(${fexp_q2} = 999, 0,
${fexp_q2})

How to properly set Firebase Realtime Database to avoid null value at the beginning of array?

I'm new to NoSQL database. Currently I'm trying to use the Firebase and integrate it with iOS. When it comes to predefine the database, with trial and error, I try to make it look like this:
When I tried to retrieve the "stories" path in iOS, I get json structure like this:
[
<null>,
{
comments: [
<null>,
1,
2,
3
],
desc: "Blue versus red in a classic battle of good versus evil and right versus wrong.",
duration: 30,
rating: 4.42,
tags: [
<null>,
"fantasy",
"scifi"
title: "The Order of the Midnight Sun",
writer: 1
]
}
]
My question is, why there's always a null at the beginning of each array? What should I do in the database editor to avoid the null?
It looks like you start pushing data to index 1 and not 0, inserting/retrieving data to/from a list starts with index 0:

LinkedIn historical company statistics giving me the wrong number of followers

I am attempting to write a backfill script that will pull in historical follower numbers for linkedin companies we are missing data for. My current script is able to get data back from linkedin, but these numbers appear incorrect for my test company. I am using this company: https://www.linkedin.com/company/3802814
I make a historical follower statistics call like so:
http://api.linkedin.com/v1/companies/3802814/historical-follow-statistics?start-timestamp=315554400&end-timestamp=1421349947&time-granularity=day&format=json
(these timestamps correspond to 01/01/1980 and 01/15/2015)
The data I'm getting back indicates 14 (not 6, as my company actually has) followers, all on random/incorrect dates, with all 0s:
{
"_total": 14,
"values": [
{
"organicFollowerCount": 0,
"paidFollowerCount": 0,
"time": 259200000,
"totalFollowerCount": 0
},
{
"organicFollowerCount": 0,
"paidFollowerCount": 0,
"time": 345600000,
"totalFollowerCount": 0
},
... (10 more similar records)
{
"organicFollowerCount": 0,
"paidFollowerCount": 0,
"time": 1296000000,
"totalFollowerCount": 0
},
{
"organicFollowerCount": 0,
"paidFollowerCount": 0,
"time": 1382400000,
"totalFollowerCount": 0
}
]
}
I would have guessed my timestamps were wrong until I saw that it's giving me more followers than I should actually have. Does anyone know what I might be doing wrong? Looking at the linkedin docs has thus far not given me any obvious answers. Data I expect would be a series of daily records updated by # of followers added on a given day. These followers were primarily added sometime in December 2014.
This is the proper request you should be making to get the information you are looking for:
GET https://api.linkedin.com/v1/companies/3802814/historical-follow-statistics?start-timestamp=315561600000&time-granularity=day&end-timestamp=1421308800000&format=json
You want to make sure you are using the timestamps in milliseconds.
The total value you are also seeing is the # of results - not the # of followers.

Resources