How to model a consitent database in alloy? - modeling

Alloy newbie here. I'm trying to model a medical database containing user and some medical information.
sig User{
name: one String,
surname: one String,
socialNumber: one String,
address: one String,
age: one Int,
registration: one UserCredential,
healthStatus: one HealthInformation
}{
age>0
}
sig UserCredential{
user: one String,
pass: one String,
mail: one String
}
sig HealthInformation{}
sig Data4Help{
users: some User,
}
pred show(d:Data4Help){
#d.users>1
}
run show for 10
The analyzer tell me the model is inconsistent:
Executing "Run show for 10"
Solver=sat4j Bitwidth=4 MaxSeq=7 SkolemDepth=1 Symmetry=20
5448 vars. 510 primary vars. 12578 clauses. 16ms.
No instance found. Predicate may be inconsistent. 0ms.
Can you guys tell me why? All I want is having the database "Data4Help" linked to some users, probably the definition of the relation is incorrect but I don't know why.
Thank you

The problem is that Alloy has some troubles with Strings. By default, the String signature defines an empty set of atoms. If you want to use Strings in your model, you will have to populate that set with "your own Strings".
See How to use String in Alloy?
In your model, you could add this simple fact
fact initPoolOfString{
String in "insert"+ "your"+"dummy" + "strings" + "here"
}

Related

Why am I unable to change values of a Mongoose object to a different type ‘directly’?

I've just spent a good hour figuring out something mind-boggling (at least to me, as a JS noob) and I'd like to understand the underlying logic (or just why it works this way, because I think it's illogical and quite unexpected).
Suppose I'm using Mongoose to retrieve documents from a database, some or all of which include a date property (created with new Date()), a numeric property, and a string property.
[{
string: 'foo',
date: '2018-10-13T21:11:39.244Z',
number: 10
},
...
{
string: 'bar',
date: '2018-10-13T21:12:39.244Z',
number: 20
}]
I thus obtain an array of objects and now want to take the date property for each object and change the value to a string, so I do something like:
doc.find({}, (err, list) => {
list.forEach((item, index) => {
list[index].date = 'new value'
})
})
But I can't do that!
I can do list[index].string = 'new value' as well as list[index].date = new Date() but I can't change values that are of a different type, in this example date and number.
However, when I do list[index]._doc.date = 'new value', which took so long to figure out because I didn't know Mongoose objects weren't just plain old objects and focused on solving problems I didn't have instead, I can modify the value just fine.
It appears that the mongoose object somehow translates obj.key to obj._doc.key only if the type of the value matches but I'd appreciate a more detailed explanation than my uneducated guesses.
I suppose you want to use multi type on a document field, Mongoose support this by "Mixed" type when you define the Schema.
You can get more detail from https://mongoosejs.com/docs/schematypes.html#mixed.

Alternatives to boxing string field or extending ALL strings in Kotlin?

Given that one can't subclass builtin types in Kotlin, I'm looking for a way to add special method functionality to specific types of string fields in a record, without applying those extension functions to all strings (even within that record type). Say, for example, I have some mutable string fields inside a record, for which I want to define special purpose behaviors.
class Customer {
// ...
var zipcode: String
var email: String
// ...
}
For zipcode, assume I'd like to be able to call
thisCustomer.zipcode.plusFour to get the +4 of the zip code (99999-9999) via regex.
For email, assume I'd like to be able to call
thisCustomer.email.domain to have a regex go get the ...#company.com
portion of the specified email.
My objectives are to:
Avoid the runtime overhead of boxing zipcode into a class Zipcode with just a
single var inside, given that the size of the Customer recordset could potentailly be millions.
Avoid the syntax of having to assign
thisCustomer.zipcode.value = "99999-9999" or thisCustomer.zipcode = Zipcode("99999-9999"), if I did end up having to box the string.
Avoid adding general String.plusFour and
String.domain extension properties, even just within the Customer
class... because zipcodes and emails could technically call each others'
extensions
I've been thinking this over and considered the following options, but struck out with each:
subclassing String: Not possible since strings (and all built-ins)
are closed
applying an interface Zip to the var declaration (var zipcode:
String, Zip): No such syntax I could find
adding inner functions within the getter itself: Syntax doesn't seem to exist for this
using objects or functions-within-functions: Couldn't think of a way
for this to work, although I might not be imaginative enough
Am I missing an obvious solution here? Even if not obvious, with all the syntactic magic of Kotlin, is there a way to make it happen? Maybe there's a way to accomplish some/all of the objectives above without using any of these approaches?
You can use type aliases to make the intention clear:
typealias ZipCode = String
val ZipCode.plusFour get() = ...
typealias Email = String
val Email.domain get() = ...
class Customer {
// ...
var zipcode: ZipCode
var email: Email
// ...
}
Unfortunately, this only clarifies intentions and doesn't stop the compiler from allowing zipcode.domain. But for now I don't think there is any way which satisfies both objectives 1 and 3.
Kotlin developers have decided not to support assignment-incompatible type aliases, which would have fit all your requirements, in favor of waiting for value classes to be available on JVM, as discussed in https://github.com/Kotlin/KEEP/issues/4.
You may create a decorator class using delegate:
class YourString(val value: String) : Comparable<String> by value, CharSequence by value {
val plusFour: String
get() = "" //your logic here
val domain: String
get() = "" //your logic here
override fun toString() = value
}
Usage:
fun String.toYourString() = YourString(this)
class Customer(var zipCode: YourString, var email: YourString)
val customer = Customer("+4 99999-9999".toYourString(), "xxx#company.com".toYourString())
println(customer.zipCode.plusFour)
println(customer.email.domain)

What is the meaning `required` in mongoose Schema?

I am writing a mongoose schema, and I would like to understand the properties of the same.
Here is my schema:
var UserSchema = new Schema({
name: String,
username: { type: String, required: true, index: { unique: true }},
password: { type: String, required: true, select: false }
});
Why required is not declared for `name' - ?
Why required declared?
What is select - true/false -means?
When the index - should declared any why?
Why required is not declared for `name' - ?
Answer: When a field is mandatory to fill then in that case we mention it as required. So here "name" is not required or mandatory field.
Why `required' declared?
Answer: As mentioned above, When a field is mandatory to be filled then in that case we mention it as required.
What is select - true/false -means?
Answer: This means that it will not be returned by default in the data when you fetch the document. you can specify if this path should be included or excluded from query results by default.
Schema options
When the index - should declared any why?
Answer: Index should be declared when you are searching data on that field frequently so when you create indexing on that field in that case it do not search that field in all the collections it will search value for that field using index and will return result very quickly.
How indexes work in mongodb
Here, these act as model for your project. So, required is used as validation and index is working as index over that field
Now you have two ways :
either put validation over here in schemas/models
or just manually create validation for form at frontend using JS/Jquery and then long route
Now your answers:
Name is not compulsory to be filled in. That's why no required is put over there.
when there is mandatory to fill any value for that field. Then required is used in schemas.
True/False enables or disables the usage of validation over that field. If you are using false means filling in for that field isn't compulsion at all. But using false is considered a good practice.
Index is special data structure which are used for increasing performance during read/search operations. It increases the speed of operations and are stored in memory.
whenever we have to validate the particular field, so we used required.
required: true means you must fill that field.
required: false means you may or may not fill that field, but its a good practice.

Storing data efficiently in MongoLab and in general

I have an app that listens to a websocket and it stores usernames/userID's (Usernames are 1-20 bytes, UserID's are 17 bytes). This is not a big deal because it's only one document. However, every round they participate in, it pushes the round ID (24 bytes) and a 'score' decimal value (ex: 1190.0015239999999).
The thing is, there is no limit to how many rounds there are and I can't afford to pay so much per month for mongolab. What's the best way to handle this data?
My thoughts:
- If there is a way to replace the _id: field in mongodb, I will replace it with the userID which is 17 bytes long. Not sure if I can do that though.
Store user data with timestamps and remove OLD data that has a score value less than 200.
Cut off user names that are more than 10 characters.
Completely remove Round ID's (Or replace the _id field with roundId). (Won't work since there are multiple roundID's in each document)
Round the decimal value to two places.
Remove Round ID's after 30 days
tl;dr
Need to store data efficiently < 500 mb in mongo lab
Documents consists of username(1-20 characters), userid(17 characters), round(Object Array) = [{round Id(24 characters), score(1190.0015239999999)}].
Thanks in advance!
Edit:
Document Schema:
userID: {type: String},
userName: {type: String},
rounds: [{roundID: String, score: String}]
Modelling 1:n relationships as embedded document is not the best except for very rare cases. This is because there is a 16MB size limit for BSON documents at the time of this writing.
A better (read more scalable and efficient approach) is to do use document references.
First, you need your player data, of course. Here is an example:
{
_id: "SomeUserId",
name: "SomeName"
}
There is no need for an extra userId field since each document needs to have a _id field with unique values anyway. Contrary to popular belief, this fields value does not have to be an ObjectId. So we already reduced the size you need for your player data by 1/3, if I am not mistaken.
Next, the results of each round:
{
_id: {
round: "SomeString",
player: "SomeUserId"
},
score: 5,
createdAt: ISODate("2015-04-13T01:03:04.0002Z")
}
A few things are to note here. First and foremost: Do NOT use strings to record values. Even grades should rather be stored as corresponding numerical values. Otherwise you can not get averages and alike. I'll show more of that later. We are using a compound field for _id here, which is perfectly valid. Furthermore, it will give us a free index optimizing a few of the most likely queries, like "How did player X score in round Y?"
db.results.find({"_id.player":"X","_id.round":"Y"})
or "What where the results of round Y?"
db.results.find({"_id.round":"Y"})
or "What we're the scores of Player X in all rounds?"
db.results.find({"_id.player":"X"})
However, by not using a string to save the score, even some nifty stats become rather cheap, for example "What was the average score of round Y?"
db.results.aggregate(
{ $match: { "_id.round":"Y" } },
{ $group: { "round":"$_id.round", "averageScore": {$avg:"$score"} }
)
or "What is the average score of each player in all rounds?"
db.results.aggregate(
{ $group: { "player: "$_id.player", "averageAll": {$avg:"$score"} }
)
While you could do these calculation in your application, MongoDB can do them much more efficiently since the data does not have to be send to your app prior to processing it.
Next, for the data expiration. We have a createdAt field, of type ISODate. Now, we let MongoDB take care of the rest by creating a TTL index
db.results.ensureIndex(
{ "createdAt":1 },
{ expireAfterSeconds: 60*60*24*30}
)
So all in all, this should be pretty much the most efficient way of storing and expiring your data, while improving scalability in the same time.
So currently you are storing three data points in the array for each record.
_id: false will prevent mongoose from automatically creating an id for the document. If you don't need roundID, then you can use the following which only stores one data point in the array:
round[{_id:false, score:String}]
Otherwise if roundID actually has meaning, use the following which stores two data points in the array:
round[{_id:false, roundID: string, score:String}]
Lastly, if you just need an ID for reference purposes, use the following, which will store two data points in the array - a random id and the score:
round[{score:String}]

Design a document database schema

I'm vainly attempting to learn how to use object databases. In database textbooks the tradition seems to be to use the example of keeping track of students, courses and classes because it is so familiar and applicable. What would this example look like as an object database? The relational database would look something like
Student
ID
Name
Address
Course
ID
Name
PassingGrade
Class
ID
CourseID
Name
StartTime
StudentClass
ID
ClassID
StudentID
Grade
Would you keep StudentClasses inside of Classes which is, in turn, inside Course and then keep Student as a top level entity?
Student
ID
Name
Address
Course
ID
Name
Classes[]
Name
StartTime
Students[]
StudentID
So you have Courses, Students and Classes, which are parts of Courses and visited by Students? I think the question answers itself if you think about it. Maybe it's clearer if you go away from the pure JSON of MongoDB and look at how you would define it in an ODM (the equivalent of an ORM in RDBs) as document based DBs don't really enforce schemas of their own (example is based on MongoEngine for Python):
class Student(Document):
name = StringField(max_length=50)
address = StringField()
class Attendance(EmbeddedDocument):
student = ReferenceField(Student)
grade = IntField(min_value=0, max_value=100)
class Class(EmbeddedDocument):
name = StringField(max_length=100)
start_time = DateTimeField()
attendance_list = ListField(EmbeddedDocumentField(Attendance))
class Course(Document):
name = StringField(max_length=100)
classes = ListField(EmbeddedDocumentField(Class))
This would give you two collections: one for Students and one for Courses. Attendance would be embedded in the Classes and the Classes would be embedded in the Courses. Something like this (pseudocode):
Student = {
name: String,
address: String
}
Course = {
name: String,
classes: {
name: String,
start_time: DateTime,
attendance_list: {
student: Student,
grade: Integer
}[]
}[]
}
You could of course put the grade info in the student object, but ultimately there really isn't much you can do to get rid of that extra class.
The whole point of an OODBMS is to allow you to design your data model as if it were just in memory. Don't think of it as a database schema problem, think of it as a data modelling problem on the assumption that you have a whole lot of VM and a finite amount of physical memory, You want to make sure that you don't have to boil an ocean of page faults (or, in fact, database I/O operations) to do the operations that are important.
In a pure OODB, your model is fine.

Resources