HTML 5 App local database - database

I am creating a Q & A app for Windows 8 Phone.
These Q & A are about 100 or so and will never change.
I am not familiar with Windows 8 Phone SDK so I have decided to stick with the HTML 5 template for this.
Now I need to save/store these QA somewhere I do not want to involve the use of database, as this is a pretty simple app that I am making and I dont want it to connect to / depend on server, I want users to be able to use and read all QA even when they are offline.
So, with these requirement I could only think of storing these QA in json format and then using jquery to read and populate the QA into HTML.
{
"categoryName": "Animal",
"categoryId": 1,
"QA": [
{
"question": "Which animal barks ?",
"answer": "dog"
},
{
"question": "Which animal moos ?",
"answer": "cow"
},
]
}
{
"categoryName": "Grammar",
"categoryId": 2,
"QA": [
{
"question": "Opposite of men ?",
"answer": "women"
},
{
"question": "Vowels ?",
"answer": "AEIOU"
},
]
}
Are there any other approaches which you can suggest ?
Please share your thoughts on this.

According to caniuse you should be able to use HTML5 IndexedDB with IE10

You say the data will never change, so I don't see why you need to use HTML5 IndexedDB.
You don't even need to store it in JSON format, just create the JS objects directly for optimal performance:
var data = [{
categoryName: "Animal",
categoryId: 1,
QA: [
{
question: "Which animal barks ?",
answer: "dog"
},
{
question: "Which animal moos ?",
answer: "cow"
},
]
},
{
categoryName: "Grammar",
categoryId: 2,
QA: [
{
question: "Opposite of men ?",
answer: "women"
},
{
question: "Vowels ?",
answer: "AEIOU"
},
]
}];

Related

Best way to store presentation-specific data in react-redux application

I know the best practice is not using a redux store to save any kind of visualization-related data. But I don't see any way to avoid that in my project. I have a simple store like this:
{
pages: {
byId: {
'0': {
id: '0',
canvases: {
byId: {
'0': {
id: '0',
layers:
{
byId: ['0':{uid:'0'}],
allIds: ['0']
}
}
},
allIds: ['0']
},
selectedId: '0'
}
},
allIds: ['0']
}
}
It just stores the document filled by pages. Each page may have one or more canvases. Each canvas has zero or more layers. Visually each page/canvas/layer is a tree of nested blocks. My idea is putting a selection frame with some handles on top of z-index of my HTML when user clicks onto a layer. The problem is that selection component is in a different DOM tree relatively to the page but at the same time I need to know a bounding rectangle of my page, canvas and layer to overlay the selection correctly. What is the best way to do that? Do I need to use a redux store to save my bounding area?
I think a good solution here will be normalizr. It takes a json like this:
{
"id": "123",
"author": {
"id": "1",
"name": "Paul"
},
"title": "My awesome blog post",
"comments": [
{
"id": "324",
"commenter": {
"id": "2",
"name": "Nicole"
}
}
]
}
and turns it into something like this:
{
result: "123",
entities: {
"articles": {
"123": {
id: "123",
author: "1",
title: "My awesome blog post",
comments: [ "324" ]
}
},
"users": {
"1": { "id": "1", "name": "Paul" },
"2": { "id": "2", "name": "Nicole" }
},
"comments": {
"324": { id: "324", "commenter": "2" }
}
}
}
Take a look at the docs for normalizr, I think it can help you.
I decided to choose MobX + MST framework: https://github.com/mobxjs. This one is covering snapshots to easily manage application states. I am even able to connect Redux Dev Tools to track my state at runtime. In addition to that it has a support of volatile states which makes sense for storing some temporary data like drag and drop mouse offset or some not tied to store visual data. And another one thing is that undo/redo logic can be implemented easily. I am originally from OOP world so MobX/MST is closer to my mindset than Flux/Redux concepts.

loop through array or json file in angular 4

I want to loop through an array of objects in angular 4 , I use a .ts file to export array as a variable in posts.ts
export var posts = [
{
"name":"art",
"title":"Art",
"items":[
{
"id": "1",
"title":"Tooling Up",
"author":"Amber Bravo",
"date":"June 14 2015",
"primaryColor":"#5a7785",
"secondaryColor":"#455a64",
"image":"https://g-design.storage.googleapis.com/production/v5/assets/tooling-up-header-a13cfd9a.svg",
"desc":"How a new generation of prototyping tools at Google will help designers build better software.",
"content":"# content goes here"
},
{
"id": "2",
"title":"Expressing Brand in Material",
"author":"Viktor Persson & Rachel Been",
"date":"July 4 2015",
"primaryColor":"#202226",
"secondaryColor":"#333",
"image":"https://g-design.storage.googleapis.com/production/v5/assets/article_brand_2x1_202226-fc539618.svg",
"desc":"Material design offers a system for designing functional and elegant software. How does your brand fit into the framework? We’ve created a step-by-step guide to staying on-brand while going material.",
"content":"# content goes here"
},
{
"id": "3",
"title":"New Design Tools",
"author":"Amber Bravo",
"date":"July 29 2015",
"primaryColor":"#3e50b4",
"secondaryColor":"#303fc3",
"image":"https://g-design.storage.googleapis.com/production/v5/assets/150727_GD_Article_ToolingUpFurther_1x1Tile-01-86c8e03e.svg",
"desc":"See Also: (More) thoughts on design tools",
"content":"# content goes here"
}
]
},
{
"name":"film",
"title":"Film",
"items":[
{
"id": "1",
"title":"Design from iOS to Android (and Back Again)",
"author":"Roman Nurik & Viltor Persson",
"date":"Aug 20 2015",
"primaryColor":"#3e50b4",
"secondaryColor":"#303F9F",
"image":"https://g-design.storage.googleapis.com/production/v5/assets/renditions/Article_iOS_to_Android_Header_3e50b4-f064882f-1240.png",
"desc":"A practical guide to designing across platforms",
"content":"# content goes here"
},
{
"id": "2",
"title":"Demystifying Density",
"author":"Sebastien Gabriel",
"date":"July 10 2015",
"primaryColor":"#00ccb8",
"secondaryColor":"#00b7a5",
"image":"https://g-design.storage.googleapis.com/production/v5/assets/article_dpi_00ccb8-34fdd39e.svg",
"desc":"Sebastien Gabriel takes one for the team with his exhaustive guide to DPI & PPI",
"content":"# content goes here"
},
{
"id": "3",
"title":"Pixate and Form 1.3",
"author":"Google Design",
"date":"May 30 2015",
"primaryColor":"#eeeeee",
"secondaryColor":"#9e9e9e",
"image":"https://g-design.storage.googleapis.com/production/v5/assets/pixate-and-form-1-3-header-2061f19f.svg",
"desc":"Discover the latest features and start designing native prototypes on your device.",
"content":"# content goes here"
},
{
"id": "4",
"title":"Welcome to the New Google Design",
"author":"Google Design",
"date":"Sep 10 2015",
"primaryColor":"#3367d6",
"secondaryColor":"#2755CC",
"image":"https://g-design.storage.googleapis.com/production/v5/assets/Article_Welcome_Header_2880-ce3ec22d.svg",
"desc":"More design, all the time",
"content":" # content goes here"
}
]
},
{
"name":"photography",
"title":"Photography",
"items":[]
},
{
"name":"design",
"title":"Design",
"items":[]
},
{
"name":"topten",
"title":"Top Ten",
"items":[]
},
{
"name":"aday",
"title":"A Day in the Life",
"items":[]
}
]
then I import it in app.componenet.ts normally with :
import { posts } from './posts';
now what I don't know is how to loop through it or how to load json file then loop through it I mean how to loop in html to display data inside the app.componenet.html
You have to pass this array to view.
#Component(...)
class AppComponent {
posts = posts;
...
And then in view you have to use *ngFor directive.
<ng-container *ngFor="let post of posts">
{{ post.title }}
</ng-container>

Query an array of users based on an array of users

Basically I'm having trouble understanding how I would figure this out.
I have a document in a mongodb collection, and that document has field called friends which is an array of usernames.
I want to query through each username in the array friends, and have an array of those user documents. I'm terrible at explaining maybe if I draw this out it'll make sense.
mongodb document:
{
"_id": {
"$oid": "59a20e65f94cb5e924af774e"
},
"name": "Nick",
"friends": ["Jones","Mark","Mike"]
}
Now with this friends array, I want to search the same collection for an object with the "name" Jones, Mark, and Mike. When I find that object, I want to put it into an array.
Basically I want it to return this, (for this example let's say Jones, Mark, and Mike only have one friend, and that friend is Nick.
[{
"_id": {
"$oid": "59a20e65f94cb5e924af774e"
},
"name": "Jones",
"friends": ["Nick"]
},
{
"_id": {
"$oid": "59a20e65f94cb5e924af774e"
},
"name": "Mark",
"friends": ["Nick"]
},
{
"_id": {
"$oid": "59a20e65f94cb5e924af774e"
},
"name": "Mike",
"friends": ["Nick"]
}]
^ an array of three objects, which are all the friends of Nick.
If you need any more explanation please let me know, I'm terrible at this type of stuff.
For the record, I'm using node, and basic mongodb (not mongoose).
I believe you are looking for $in operator.
// doc.friends = ["Jones","Mark","Mike"]
db.collection.find({ name: { $in: doc.friends }})

Generate query results based on tags in PouchDB

I'm new to NoSQL but have decided to use PouchDB for an Angular Application I am creating.
There are going to be a series of questions (about 1000 in total) which each have their own tags. Each object shouldn't have more that 6 or 7 tags. Example data is:
{
"text": "Question?",
"answers": [
{ "text": "Yes", "correct": true },
{ "text": "No", "correct": false }
],
"tags": ["tag1", "tag3"]
},
{
"text": "Question?",
"answers": [
{ "text": "Yes","correct": true },
{ "text": "No", "correct": false }
],
"tags": ["tag2", "tag3"]
}
I'm at a total loss on how I can query the db in order to retrieve only questions that have "tag2" or questions that have "tag1" and "tag3".
I came across the question found at How to query PouchDB with SQL-like operators but can't seem to wrap my head around how it works. I tried to modify it based on my data and I always get 0 results when querying the database.
I guess my biggest struggle is comparing it to SQL when it isn't. Does anyone know how I can go about creating a query based on specific tags?
Yup, you create a map/reduce query like this:
// document that tells PouchDB/CouchDB
// to build up an index on tags
var ddoc = {
_id: '_design/my_index',
views: {
my_index: {
map: function (doc) {
doc.tags.forEach(function (tag) {
emit(tag);
});
}.toString()
}
}
};
// save it
pouch.put(ddoc).then(function () {
// success!
}).catch(console.log.bind(console));
Then you query it:
pouch.query('my_index', {key: myTag, include_docs: true}).then(function (res) {
// got a result
}).catch(console.log.bind(console));
If you want to find multiple tags, you can just keys instead of key.
BTW this will be easier in the future when I add $elemMatch and $in to pouchdb-find.

MongoDB Array Query Performance

I'm trying to figure out what the best schema is for a dating site like app. User's have a listing (possibly many) and they can view other user listings to 'like' and 'dislike' them.
Currently i'm just storing the other persons listing id in a likedBy and dislikedBy array. When a user 'likes' a listing, it puts their listing id into the 'liked' listings arrays. However I would now like to track the timestamp that a user likes a listing. This would be used for a user's 'history list' or for data analysis.
I would need to do two separate queries:
find all active listings that this user has not liked or disliked before
and for a user's history of 'liked'/'disliked' choices
find all the listings user X has liked in chronological order
My current schema is:
listings
_id: 'sdf3f'
likedBy: ['12ac', 'as3vd', 'sadf3']
dislikedBy: ['asdf', 'sdsdf', 'asdfas']
active: bool
Could I do something like this?
listings
_id: 'sdf3f'
likedBy: [{'12ac', date: Date}, {'ds3d', date: Date}]
dislikedBy: [{'s12ac', date: Date}, {'6fs3d', date: Date}]
active: bool
I was also thinking of making a new collection for choices.
choices
Id
userId // id of current user making the choice
userlistId // listing of the user making the choice
listingChoseId // the listing they chose yes/no
type
date
I'm not sure of the performance implications of having these choices in another collection when doing the find all active listings that this user has not liked or disliked before.
Any insight would be greatly appreciated!
Well you obviously thought it was a good idea to have these embedded in the "listings" documents so your additional usage patterns to the cases presented here worked properly. With that in mind there is no reason to throw that away.
To clarify though, the structure you seem to want is something like this:
{
"_id": "sdf3f",
"likedBy": [
{ "userId": "12ac", "date": ISODate("2014-04-09T07:30:47.091Z") },
{ "userId": "as3vd", "date": ISODate("2014-04-09T07:30:47.091Z") },
{ "userId": "sadf3", "date": ISODate("2014-04-09T07:30:47.091Z") }
],
"dislikedBy": [
{ "userId": "asdf", "date": ISODate("2014-04-09T07:30:47.091Z") },
{ "userId": "sdsdf", "date": ISODate("2014-04-09T07:30:47.091Z") },
{ "userId": "asdfas", "date": ISODate("2014-04-09T07:30:47.091Z") }
],
"active": true
}
Which is all well and fine except that there is one catch. Because you have this content in two array fields you would not be able to create an index over both of those fields. That is a restriction where only one array type of field (or multikey) can be be included within a compound index.
So to solve the obvious problem with your first query not being able to use an index, you would structure like this instead:
{
"_id": "sdf3f",
"votes": [
{
"userId": "12ac",
"type": "like",
"date": ISODate("2014-04-09T07:30:47.091Z")
},
{
"userId": "as3vd",
"type": "like",
"date": ISODate("2014-04-09T07:30:47.091Z")
},
{
"userId": "sadf3",
"type": "like",
"date": ISODate("2014-04-09T07:30:47.091Z")
},
{
"userId": "asdf",
"type": "dislike",
"date": ISODate("2014-04-09T07:30:47.091Z")
},
{
"userId": "sdsdf",
"type": "dislike",
"date": ISODate("2014-04-09T07:30:47.091Z")
},
{
"userId": "asdfas",
"type": "dislike",
"date": ISODate("2014-04-09T07:30:47.091Z")
}
],
"active": true
}
This allows an index that covers this form:
db.post.ensureIndex({
"active": 1,
"votes.userId": 1,
"votes.date": 1,
"votes.type": 1
})
Actually you will probably want a few indexes to suit your usage patterns, but the point is now can have indexes you can use.
Covering the first case you have this form of query:
db.post.find({ "active": true, "votes.userId": { "$ne": "12ac" } })
That makes sense considering that you clearly are not going to have both an like and dislike option for each user. By the order of that index, at least active can be used to filter because your negating condition needs to scan everything else. No way around that with any structure.
For the other case you probably want the userId to be in an index before the date and as the first element. Then your query is quite simple:
db.post.find({ "votes.userId": "12ac" })
.sort({ "votes.userId": 1, "votes.date": 1 })
But you may be wondering that you suddenly lost something in that getting the count of "likes" and "dislikes" was as easy as testing the size of the array before, but now it's a little different. Not a problem that cannot be solved using aggregate:
db.post.aggregate([
{ "$unwind": "$votes" },
{ "$group": {
"_id": {
"_id": "$_id",
"active": "$active"
},
"likes": { "$sum": { "$cond": [
{ "$eq": [ "$votes.type", "like" ] },
1,
0
]}},
"dislikes": { "$sum": { "$cond": [
{ "$eq": [ "$votes.type", "dislike" ] },
1,
0
]}}
])
So whatever your actual usage form you can store any important parts of the document to keep in the grouping _id and then evaluate the count of "likes" and "dislikes" in an easy manner.
You may also not that changing an entry from like to dislike can also be done in a single atomic update.
There is much more you can do, but I would prefer this structure for the reasons as given.

Resources