Memory Based Data Storage - java

I need to load instances of an Account class
class Account {
private String firstName;
private String lastName;
private String email;
...
}
to memory for a quick access. I can use a Java collection class to store the data. I also need to search the data. Since the email address needs to be unique, I am thinking of using map with an email address as the key. That approach won't help if searching the first name and last name are required. I can use filters for searching on first name and last name.
Any better approach?

You can maintain several different Java collections or use in-memory databases with better searching capabilities or Java object databases.
However, see also Coollection. It's interesting.

If you want to search for stuff, you want to use an indexed collection like Data Store:
https://github.com/jparams/data-store
Example:
Store<Account> store = new MemoryStore<>() ;
store.add(new Account("Ed", "Smith", "ed.smith#gmail.com"));
store.add(new Account("Fred", "Smith", "fred.johnson#hotmail.com"));
store.add(new Account("Freda", "Pinto", null));
store.index("firstName", Account::getFirstName);
store.index("lastName", Account::getLastName);
Account ed = store.getFirst("firstName", "Ed");
Account smiths = store.get("lastName", "Smith");
With data store you can create case-insensitive indexes and all sorts. If you are doing a lot of lookups, you definitely want to use a library like this.

Related

Push data from a dataframe to a Map where values are List of objects in Scala

I am working on a Scala codebase and I have to implement a scenario which uses some data structure to populate information for further processing.
The gist of the problem is,
I have a dataframe studentDf which has the student marksheet information eg.
Name, ID, Subject, Details, Marks, isFail
Now there can be multiple records for the same Name-ID mapping. I have to reflect the scenario where if the student has failed in any subject, the details (and the corresponding record) will pop up in a resultDf. And if he has not failed in any subject (congratulations!!!) then we can populate any record corresponding to the Name-ID mapping.
Basically what I would do in Java 8 for this is,
Assuming I have List<StudentMarks> studentMarksList => list of all the marks of all the students.
Map<String, List<StudentMarks>> studentToMarkMapping = new HashMap<>();
studentMarksList.stream().foreach(studentMark->{
studentToMarkMapping.computeIfAbsent(studentMark.getName()+"_"+studentMark.getID, k => new ArrayList<>()).add(studentMark);
}
Set<Student> resultSet = new HashSet<>();
for(Map.Entry<String,List<StudentMarks>> studentToMark : studentToMarkMapping){
List<StudentMarks> studentMarks = studentToMark.getValue();
for(StudentMarks studentMark : studentMarks){
if(studentMark.getFailed() == true){//Return corresponding failed subject record
resultSet.add(studentMark);
break;
}
}
resultSet.add(studentMark.get(0)); // just add any subjectMark for student who has passed all subjects
}
In Scala to do the same, I was trying to load the data into a Mutable Map, but to populate multiple records for the same student into a list and then find out whether he has failed in any or not, I am getting stuck. I see the concept of using ListBuffer which is a mutable variant of a list, but I am confused how to use it. It is possible that we can do without Map as well, but I tried some other ways which didn't end up working.
If somebody can provide any help on this, would be great. Thanks a lot!!!

Querying by attribute in Riak

I'm developing an app with Riak and java. Basically I want to store news, for which I have an object with this attributes:
public String title;
public String author;
public String URL;
public ArrayList<String> categories;
public String description;
public String release;
It's working properly but now I want to allow users to search for news by keywords.
The problem is that I only find in the java client documentation queries by primary key, which are done like this:
RiakClient client = RiakClient.newClient(10017, "127.0.0.1");
Location location = new Location(new
Namespace("TestBucket"),"TestKey");
FetchValue fv = new FetchValue.Builder(location).build();
FetchValue.Response response = client.execute(fv);
// Fetch object as String
String value = response.getValue(String.class);
System.out.println(value);
client.shutdown();
Is there a way to query by attributes? For example, could you search if a word is in the title?
Because right now the only option I see is to get all the objects from the database and search by hand, which seems very inefficient to me.
Yes, there two ways to query things by attributes, either using secondary indexes (so called 2i), or by using Riak Search. I suggest you start by using secondary index, it's easy enough. Basically when you write data, you need to decide which attribute you want to be indexed. Then you can query these indexes. They can be numeric or alphanumeric, and you can query ranges.
See https://docs.riak.com/riak/kv/latest/using/reference/secondary-indexes/index.html
And example using 2i with HTTP API: https://docs.riak.com/riak/kv/latest/developing/api/http/secondary-indexes/index.html
Check out the doc of the java client you're using.

Are there alternatives to FileDataModel?

I'm new to mahout and this field of big data.
In general data doesn't come as a (long, long, Double) all the time.
So are there alternatives to FileDataModel?
DataModel model = new FileDataModel(new File("Ratings.csv"));
Users and items are identified solely by an ID value in the framework.
Further, this ID value must be numeric; it is a Java long type through
the APIs. A Preference object or PreferenceArray object encapsulates
the relation between user and preferred items (or items and users
preferring them).
I have recently faced the same issue. I had user id UUID type. But I had to add additional table with numeric user id and original UUID user id. Later checking the documentation i have found this explanation. According other implementation of DataModel :
A DataModel is the interface to information about user preferences. An
implementation might draw this data from any source, but a database is
the most likely source. Be sure to wrap this with a
ReloadFromJDBCDataModel to get good performance! Mahout provides
MySQLJDBCDataModel, for example, to access preference data from a
database via JDBC and MySQL. Another exists for PostgreSQL. Mahout
also provides a FileDataModel, which is fine for small applications.
You can build DataModel from Database.
Here is a example for PostgreSQL:
Intercafe looks like this:
PostgreSQLJDBCDataModel(DataSource dataSource, String preferenceTable, String userIDColumn, String itemIDColumn, String preferenceColumn, String timestampColumn)
Initalization:
source = new PGPoolingDataSource();
source.setDataSourceName(properties.getProperty("DATABASE_NAME"));
source.setServerName("127.0.0.1");
source.setDatabaseName(properties.getProperty("DATABASE_NAME"));
source.setUser(properties.getProperty("DATABASE_USER"));
source.setPassword(properties.getProperty("DATABASE_PASS"));
source.setMaxConnections(50);
DataModel model =new PostgreSQLJDBCDataModel(
source,
"mahout_teble",
"user_id",
"item_id",
"preference",
"timestamp"
)
)

How to generate a random string for ID/Name of an Entity instead of a number?

I'm working with the low-level datastore API. I've created an entity like this:
Entity entity = new Entity("Error");
entity.setProperty("description", "foo");
In the datastore viewer, I ses this:
Key Write Ops ID/Name description
----------------------------------------------
ahN0c... 4 259 foo
So the ID/Name field will be generated for me automatically since I'm not supplying anything in the Entity constructor. It generates an "ID" instead of a "Name", which is a number rather than an opaque string (like the "Key" value).
Is there a way to have the datastore generate a random "Name" instead of an "ID" for the Entity's "ID/Name" field?
I ask because if I share this ID with third parties, they could start to figure out roughly how many Error instances I have in my system. I'd rather give them an opaque string for the lookup ID, similar to what's in the auto-generated "Key" field. But I don't see a way to do this.
Thanks
For a similar task I used UUID to create a random string.
String uuid = UUID.randomUUID().toString();
You can use com.google.appengine.api.datastore.KeyFactory, combining the answer from #Devolus, it would look like
final Key key = KeyFactory.createKey("Error", UUID.randomUUID().toString());
final Entity e = new Entity(key);
You could even pass around the String representation of your Entitie's key via KeyFactory.keyToString(key) , may be after an encrypting depending on your security needs.

Getting all users with a Role in Liferay

I'm new to Liferay development in general, so feel free to point out if I'm going about stuff totally the wrong way.
I'm trying to get a DynamicQuery object of all users within a certain group (I'll use this object to further filter another query I'll do against the message board). The User interface seems to have a roleIds property that I might be able to use, since I already know the roleId I'm interested in. But I can't find the proper way to query if roleIds contains a certain value.
Any ideas on what I want to do?
PS: I would have the exact SQL query I could ask directly, but I'd rather use Liferay's own connection pool, without needing to do some weird ext project thingy.
You don't need a DynamicQuery. These are the methods you are looking for in the classes that Dirk points out:
long[] UserServiceUtil.getRoleUserIds(long roleId)
or
long[] UserLocalServiceUtil.getRoleUserIds(long roleId)
List<User> UserLocalServiceUtil.getRoleUsers(long roleId)
Remember that the methods in the classes XXXLocalServiceUtil are not checking the permissions of the current user.
EDIT: If you are looking for all users with a given role within a given community:
long companyId= _X_; //Perhaps CompanyThreadLocal.getCompanyId() if you don't have it anywhere else?
Role role=RoleLocalServiceUtil.getRole(companyId, "Example Role");
Group group=GroupLocalServiceUtil.getGroup(companyId, "Example Community");
List<UserGroupRole> userGroupRoles = UserGroupRoleLocalServiceUtil.
getUserGroupRolesByGroupAndRole(groupId, role.getRoleId());
for(UserGroupRole userGroupRole:userGroupRoles){
User oneUser=userGroupRole.getUser();
}
The easiest way to access liferays own objects is by using the XXXServiceUtil classes (e.g. RoleServiceUtil.getUserRoles(userId)). Thus you rarely have to deal with any SQL directly. Either the RoleServiceUtil or UserServiceUtil might have what you need.
The roles of an Organizations are stored in the table UserGroupRole, so if you want to get the owner of an Organization you must use the following code:
boolean isOrgOwner =
UserGroupRoleLocalServiceUtil.hasUserGroupRole(
usr.getUserId(),
this.currentOrganization.getGroupId(),
RoleConstants.ORGANIZATION_OWNER);
If you want to retrieve all the Organization Owners of an organization:
List<User> administrators = new LinkedList<>();
List<UserGroupRole> allOrganizationAdministrators =
UserGroupRoleLocalServiceUtil.getUserGroupRolesByGroupAndRole(
this.currentOrganization.getGroupId(), roleId);
for (UserGroupRole userGroupRoleTemp : allOrganizationAdministrators) {
administrators.add(userGroupRoleTemp.getUser());
}
Cheers!

Categories

Resources