mongo db indexes on embedded documents - arrays

I have a domain object model as below...
#document
Profile
{
**social profile list:**
SocialProfile
{
**Interest list:**
{
Interest
{
id
type
value
}
...
}
...
}
Each profile can have many social profiles, in each social profile there are many interests related to the profile via the specific social profile ( social profile represent social network like Facebook), each interest is also embedded document with the fields id , type , value.
So I have two questions..
can I index few fields separately in the embedded document interest?
can I create compound index in the embedded document interest?
I guess the complexity in my model is the deep level of the embedded document which is 2.. and that the path to that document is via arrays...
can it be done in spring way via metadata annotations? if you think my model is wrong please let me know I am a newbie on mongo
Thanks

You can index separately on the fields in an embedded document.
You can also create a compound index on the fields, so long as no more than one field is an array.
These might offer more answers:
http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeys
http://www.mongodb.org/display/DOCS/Multikeys

Related

Retrieving data from referenced key table - Laravel-4

The structure of concerning tables is as follows (MySQL):
//Table Name : team
tid PK
team_name (varchar)
//Table Name : fixture
fid PK
home_team_id FK |_ both referenced to 'tid' from 'team' table
away_team_id FK |
My aim is to retrieve the team names. Considering this structure, I think I'll have to retrieve home_team_id and away_team_id and then do something like
Fixture::where('tid','=',$home_team_id)->get();
My question is, is this the correct way to accomplish what I aim to do?
and
should this be done from the controller? (if so, then I'll have to do two queries from same function)
First, rather than having your primary keys be tid and fid, just keep them both as id. This is not only best practice, but will allow you to more easily use Laravel's Eloquent ORM as it by default assumes your primary key column is named id.
Second thing, make sure your table names are in plural form. Although this is not necessary, the example I'm about to give is using Laravel defaults, and Laravel assumes they are in plural form.
Anyway, once you've 'Laravelized' your database, you can use an Eloquent model to setup awesome relationships with very minimal work. Here's what I think you'd want to do.
app/models/Team.php
class Team extends Eloquent {
// Yes, this can be empty. It just needs to be declared.
}
app/models/Fixture.php
class Fixture extends Eloquent {
public function homeTeam()
{
return $this->belongsTo('Team', 'home_team_id');
}
public function awayTeam()
{
return $this->belongsTo('Team', 'away_team_id');
}
}
Above, we created a simple model Team which Laravel will automatically look for in the teams database table.
Second, we created model Fixture which again, Laravel will use the fixtures table for. In this model, we specified two relationships. The belongsTo relationship takes two parameters, what model it is related to, in both cases here they are teams, and what the column name is.
Laravel will automatically take the value in away_team_id and search it against the id column in your teams table.
With just this minimal amount of code, you can then do things like this.
$fixture = Fixture::find(1); // Retrieves the fixture with and id of 1.
$awayTeam = $fixture->awayTeam()->first(); // var_dump this to see what you get.
$homeTeam = $fixutre->homeTeam()->first();
Then you can proceed as normal and access the column names for the tables. So say you have a 'name' column in the teams table. You can echo out the the home team name from the fixture like so.
$fixture = Fixture::find(1); // Get the fixture.
echo $fixture->homeTeam->name;
It's nearly 2AM, so there might be an error or two above, but it should work.
Make sure you check the docs for Eloquent, especially the bits relating to relationships. Remember to name your columns and tables in the way Laravel wants you to. If you don't, there are ways to specify your custom names.
If you want to get even more fancy, you can define the inverse relationship like this on your Team model.
app/models/Team.php
class Team extends Eloquent {
public function fixturesAtHome()
{
return $this->hasMany('Fixture', 'home_team_id');
}
public function fixturesAway()
{
return $this->hasMany('Fixture', 'away_team_id');
}
}
Then to get all of a particular team's home fixtures...
$team = Team::find(1); // Retreive team with id of 1;
$homeFixtures = $team->fixturesAtHome();

solr search based on user

I am newbie to solr. So please bear with me.
Use cases
User can share his photos to friends or publicly or make it private.
User can search for people or photos(he should view only public photos, shared with him).
I have denormalized my relational data to solr schema. I have merged the user object & photo object into solr schema
So,
If user jack (user 3) is searching for "picnic" He shouldn't see the photo_1 but see photo_2.
If user venu is searching for "picnic" He should see the photo_1 and photo_2.
How can I force solr to look into friends_ids, share_level field? can I do with facet.field? Is dynamic fields work for this case? I have read some tutorials but I am not getting clear picture.
Hope you guys shed some light on this. So that I can take forward. I hope this should be possible.
Thanks in advance!
You should have a string field for share_level, with possible value of private, public, friends.
You should also have a multiValued field for friends_ids,
and it should store each user id instead of the current CSV format
NOTE: you should revised this column type, NEVER use CSV in mysql, use a proper entity relationship
So, once you have the field ready, and complete the reindex,
to search for photo will be just:
+name:$search +(share_level:public (+share_level:friends +friends_ids:$uid))
$search = picnic
$uid = 3 (jack)

Opa : insert new element to the Database

I'm in OPA for some days now and I really start to like it. I'm attending the first year of computer science and we make some database class the next year-
The little I know about Databases are from php, I have used MySQL with php and SQLlite with c++. But this type of database is a bit different from what I've seen.
I have followed the guide about database in OPA http://doc.opalang.org/manual/Hello--database but I have a question:
In the guide we declare a new Database:
type user_status = {regular} or {premium} or {admin}
type user_id = int
type user = { user_id id, string name, int age, user_status status }
database users {
user /all[{id}]
/all[_]/status = { regular }
}
We learn how to read this database and make some query to this database with Maps, but how do I add a new element? I was testing a bit:
/users/all[{id:0}]/name<-getusername;
but id should be auto increment, from the little I know.
Thanks everyone for the help =D
I really want to get in OPA, the little I have make is really impressive!
mongoDB and auto-increment
With mongoDB (the default Opa database) there is no auto-increment (like in SQL), for scalability reason.
But if you really need one, you can use a counter to create this feature yourself:
database users {
user /all[{id}]
int /fresh_key
/all[_]/status = { regular }
}
And increment the key each time you use it: /users/fresh_key++
Random fresh key
You can also generate a random id, for example with something like Random.string(6)
Read this thread to learn more about this technique: http://lists.owasp.org/pipermail/opa/2012-April/001052.html
User defined unique key
But if you are dealing with users, maybe you already have a unique key: what about using "login" or "email" as the unique key?
You can also use Date.in_milliseconds(Date.now_gmt()) for a more unique id, maybe concatenated with the user id

In a Big Table, is it normal to key values in child (sub) collections?

I'm using Google App Engine and thus Big Table.
I have a person entity that looks like this:
{
// This property would be encoded into JSON and saved un-indexed as db.Text()
phone_numbers:
{
'hHklams8akjJkaJSL': // <-- Should I key this object?
{
number:'555-555-5555',
type:'mobile',
},
etc...
},
// This property is an array of strings.
// It is searchable so that a query could be run to find all
// people with a particular phone number:
// "SELECT * FROM person WHERE phone_number_search_property =
// '5555555555'"
phone_number_search_property:['5555555555','other phone numbers...'],
first_name:'...',
etc...
}
The phone_number property is stored as a blob of unindexed text in JSON format (db.Text). If I want to refer to a particular phone number in this situation, I decode the json, then get the phone number with the particular key that I am looking for.
The phone_number_search_property is used for searching. It enables a search by phone number: "SELECT * FROM person WHERE phone_number_search_property = '5555555555'"
What is a good way to refer to a phone number inside of an entity in this situation? Here, I have each value keyed using a UUID. Is this a "normal" and accepted way of doing things? If not, what is?
Thanks!
If data object is really just part of another object and is never accessed without the "parent" object (as is the case with phone number and person) then IMHO it's ok to serialize it and store it inside the "parent" object. So what you did is OK.
You search persons by phone number, so the solution to have additional property with (normalized) phone numbers is working. If you'd need to search on additional property, then it would not work (e.g. limiting search to only mobile numbers).
Why do you key serialized phone numbers by a hashed string (I assume you generate it via UUID.fromString(String))? Just use the (normalized) phone number - it is unique.

CakePHP Access Allocation on Role Based specific Data Access

My project requirement is something like this:
On Top, there will be Administrator, who will have all d access, first level
Under Administrator, there will be Department Heads, who will have all d access, apart from Creating Department Heads
Under Department Head, there will Other Members, who will be managing their allocated department wise data.
Now, all different department heads will have their own information and members, and all department heads / Members will have access to their own specific records, which they are entering / managing.
Now, with CakePHP's ACL Component, I can divide the roles and their access level, but all department heads can see the other department head's information, as they will have same level of access, and All Other Members can see the other members information on diff departments, as of they will have same level of access.
My project complexity is that - they should be visible only their assigned or created information / data, though they have same level / role assignments as of others.
Can anyone suggest me best suitable option, to manage all these things with already available plug-ins with CakePHP.
I can work by customizing the default ACL Component, but that will take some more amount of time, than what is expected.
Any better ideas / suggestions would be appreciated !
the way i see it, ACL is not that magical. For exemple: ACL could manage the permissions to tell who has access to add/edit/remove a product.. but it wont be able to change a query to filter the products accordingly to the defined permissions (like "users from department A can only see products from department A").. well actually that's a lie, ACL could manage that but it might not be practical, because every time you add a product you'd have to create an ACO, and set the permission in the AROS_ACOS table and since the AROS is a tree structure, so it could easily become a nigthmare, if your planning to query your data
I'd use a group-only ACL to control the access to certain pages/actions and make rules like:
"Department Head can access the page
'products list' and add/delete/modify
products"
"Administrators can access
all pages"
"Other users can access
'products list' and they can add
products but not delete them"
and i'd adjust my queries accordingly to the connected user, so in the controller of 'products list' page, i'd do something like:
If connected user blongs to Department Head then select all products where product.department_id=connected_user.department_id
If connected user is Admin then select all products
if you have too much queries and you dont want to do thousands of if's sentences, you could create a component, a behavior or maybe extend the find() method in the app_model. The idea is to catch all queries and check if one of the models used on the query have field called "department_id", if they do then add the model.department_id=connected_user.department_id condition to the query.
I did that for one website that can be seen in multiple languages and each language has it's own users, data, logs, etc., and there's one Admin that can see all the info.. and it's working great for me =)
Good Luck!
EDITED:
the behavior i use is:
<?php
class LocalizableBehavior extends ModelBehavior {
/**
* Filter query conditions with the correct `type' field condition.
*/
function beforeFind(&$model, $query)
{
/**
* Condition for the paginators that uses joins
*/
if(isset($query['joins']) && !empty($query['joins'])){
foreach($query['joins'] as $key => $joinTable){
if(ClassRegistry::init($joinTable['alias'])->hasField('lang')){
$query['joins'][$key]['conditions'][] = $joinTable['alias'].".lang = '".$_SESSION['lang']."'";
}
}
}
/**
* condition for the normal find queries
*/
if($model->hasField('lang') && $model->name != "User"){
$query['conditions'][$model->name.'.lang'] = $_SESSION['lang'];
}
return $query;
}
}
?>
it's quite simple really, i change the query to add a condition to match to the current language ($_SESSION['lang']). In the controller all i need to do is to attach the LocalizableBehavior and use find method as usual:
$this->Products->find('all');

Resources