Query on array property or embedded property - java

consider following classes:
class Basic{
String id;
Double val;
//some other member variables
}
class NodeBO{
List<String> id;
Type type;
// list of id from objects of Basic class in data below
Map<ChEnum, Basic> data;
addBeans(NodeBO nodeBO, Node node){
// in transaction...
node.setProperty("priperties", nodeBO.toString());
// is it ok to convert to array? or should be converted to JSON string?
node.setProperty(GraphElementProps.id,toArray(nodeBO.id));
node.setProperty(GraphElementProps.type, nodeBO.type);
}
#override
toString(){
//return json of this object
}
}
enum ChEnum{
CH1(1), CH2(2);
// constructor and some methods
}
nodes are indexed using autoIndexer:
AutoIndexer<Node> nodeAutoIndexer = GRAPH_DB.index().getNodeAutoIndexer();
nodeAutoIndexer.startAutoIndexingProperty(GraphElementProps.id);
nodeAutoIndexer.setEnabled(true);
GRAPH_NODE_AUTO_INDEX = nodeAutoIndexer.getAutoIndex();
Here I'm storing GraphElementProps.id as node property (by converting to array). Does it take array (of string) as property? Or should I convert list to JSON-string and then store?
I want to be able to query on this array given with queryId. e.g. query on node-index to get nodes in which node.getProperty(GraphElementProps.id) contain given queryId? i.e. something like:
// how to do this?
GRAPH_NODE_AUTO_INDEX.get(/*Nodes whose id contain queryId*/);
Or is it (somehow) possible to make id property of Basic class indexable and searchable? How to index such properties, if possible? and how to query them?
I'm unable to understand but is it something related to Spring-data-neo4j? I'm completely new to Spring-data-neo4j.

I think the best solution is to use Spring-data-neo4j. This will allow to index embedded fields and query on them.

Related

Validating an object with properties all of type String checking that they will be able to be parsed to the correct data type

I have an entity that is populated directly from an Excel file so every property is of type String. I am then mapping from this property to an actual entity that has all of the correct data types set using parses with try catch. For example:
InputEntity:
public class ProductInput {
String name;
String color;
String price;
String date;
}
ActualEntity:
public class Product {
String name;
String color;
Double price;
Date date;
}
Prior to doing the actual mapping I would like to log any errors to the database using an Error class I created.
The ultimate goal would be to make sure each value coming from the InputEntity is not null or empty and is the correct type (able to be set in the Actual Entity without any error). I want to use reflection to loop through the fields of the Product class and find the matching field on the ProductInput class. Then checking its value with the correct parse function to make sure it will eventually be able to be set in the Product entity. If there is an error I am going to create an error record that includes the property name that failed and store it in the database saying which input field has a problem.
Is reflection the correct way to go about this? I want the function to be generic enough to handle any classes as the input and actual assuming the properties of the input entity will always be string and the property names will match.
I was thinking somewhere along the lines of:
public validateFields(Class<T> inputClass, Class<T> destinationClass) {
Field[] inputFields = inputClass.getDeclaredFields();
Field[] destinationFields = destinationClass.getDeclaredFields();
for (Field field: destinationFields) {
// Check for same field in inputClass
// If it exists confirm value of field is not null or empty
// Additionally confirm the value of field can be parsed to the type of the destinationField
// Create error entity with property name if there is a problem
}
}

Mapping POJOs to case classes with immutable lists during deserialisation

I am coming from Java background and trying to understand how to model Domain classes/POJOs in Scala.
I am trying to Deserialize JSON response from a RestAPI and my Java POJOs are as follows:
#Data
public class ColumnResponse {
private String id;
private String name;
private String type;
...
}
k
#Data
public class DataSetGetResponse {
private String id;
private List<ColumnResponse> columns;
...
}
Now I have created following Case Classes
case class DataSetGetResponse (id: String,
columns: List[ColumnResponse]
.... )
case class ColumnResponse (id: String,name: String ...)
I am trying to use https://sttp.readthedocs.io/en/latest/json.html#json4s library for HTTP communication and json4s for deserialization.
Questions:
1) In the DataSetGetResponse case class, field "columns" is a List.By default this is an immutable list. How the Deserialization library add new DataColumnGetResponse objects to this immutable list? Do I have to declare this as mutable ?
2) There is a field called 'type' field in the ColumnResponse POJO. In Scala 'type' is a reserved keyword.How to handle this case?
Answer the first one:
An immutable object can be mutated with the copy function:
dataSet.copy(columns = newResp :: dataSet.columns)
For more complex tasks you can use Lenses see for example here: enter link description here
Answer the second one:
If it is a reserved word you can do it like
case class ColumnResponse (id: String, name: String, `type`: String)
This answer addresses the following aspect of the question:
How the Deserialization library add new DataColumnGetResponse objects
to this immutable list?
Let us consider a simplified version of the problem:
JsonMethods.parse("""[1,2,3]""").extract[List[Int]]
How does json4s deserialise [1,2,3] into immutable List[Int]? First it parses the raw string into an intermediary AST (abstract syntax tree) data structure where it represents the list like so
case class JArray(arr: List[JValue]) extends JValue
We see here that arr is an immutable list. The key line that builds it up after parse executes is in JsonParser
def newValue(v: JValue): Unit = {
...
case a: JArray => vals.replace(JArray(v :: a.arr))
...
}
Note how the operator :: in v :: a.arr adds an element at the beginning of this list and returns a new list with v added in. This means since there are three elements in [1,2,3] the following three lists are created by json4s in the process of deserialisation
JArray(List(JInt(1))
JArray(List(JInt(2), JInt(1)))
JArray(List(JInt(3), JInt(2), JInt(1)))
Again note these are three separate lists.
Next, after internal AST is created, actual deserialisation to List[Int] takes place by calling extract[List[Int]]. The key component that does this for lists is CollectionBuilder
private class CollectionBuilder(json: JValue, tpe: ScalaType)(implicit formats: Formats) {
...
val array: Array[_] = json match {
case JArray(arr) => arr.map(extractDetectingNonTerminal(_, typeArg)).toArray
...
}
Note how we simply map over AST arr built up during parsing step and convert each element to the model of type typeArg, which in our simple case is Int but in your case would be DataColumnGetResponse.

How to efficiently compare two objects of same Class and check which are the fields that differ?

I want to write a generic function that accepts two objects of same entity class and compares the fields that are different and returns List of all the changes made to particular fields along with time.
One among the many entity classes would be say Member as follows
public class Member {
String firstName;
String lastName;
String driverLicenseNumber;
Integer age;
LocalDateTime timestamp;
}
In the DB, I have a table called member_audit that gets populated with old data whenever there is a change in member table using triggers (Similarly for other entities).
The List of resource for each of the entity I would be returning is something like
public class MemberAuditsResource {
private String field;
private LocalDateTime on;
private String changeType;
private String oldValue;
private String newValue;
}
I can only think of writing a function for each entity separately like this
private List<MembeAuditsResource> memberCompare(Member obj1, Member obj2) {
//Compare every field in both the objects using if else and populate the resource.
}
And then calling the above function to compare every pair of record in the entity_audit table.
The code would be very large to compare every field and multiplied by different entities.
Is there a better and efficient way?
If you extend the ideas to compare the object graph , it is not a trivial problem. So, the efficient way is not to re-inventing the wheel but use an existing library such as JaVers :
Member oldMember = new Member("foo" ,"chan" ,"AB12" , 21 ,LocalDateTime.now());
Member newMember = new Member("bar" ,"chan" ,"AB12" , 22 ,LocalDateTime.now());
Diff diff = javers.compare(oldMember, newMember);
for(Change change: diff.getChanges()) {
System.out.println(change);
}
Then , you can get something like:
ValueChange{ 'firstName' changed from 'foo' to 'bar' }
ValueChange{ 'age' changed from '21' to '22' }
Convert both object to a Map using JSON objectMapper.convertValue method. Then you can easily compare the keys/values of the two maps and create a list of differences.

Collect any particular attribute value of a fact in a list in drools

I have a pojo similar to below pojo
public class TestData {
int number;
String name;
//Getters, setters, rest of class
}
The multiple object of this pojo is inserted in the rule engine. Now I want a list having name attribute collected from all inserted pojo through rule.
i.e. List<String> for the name from the inserted pojo.
Thanks
Shorav
This very simple rule collects all names in TestData facts:
rule "collect names"
when
accumulate( TestData( $n: name ); $names: collectList( $n ) )
then
// ... $names is a List containing String objects
end
Note that the List $names is compiled as a List<?>. Processing on the right hand side may have to cast list elements to String.

Hibernate search range in a List<Integer>

I am starting with hibernate search and am struggling with a query on a List<Integer>
I created a bridge to translate the list<Integer> to a string. From this, I am able to search by keyword exact matches on any item on the list, but I don't seem to be able to query it using range.
My entity A has an attribute "b" defined as List.
I would like to know if anyone can help me to get to query all the A entities which have any of the b elements inside a defined range?
For example:
an A instance with the following collection {1,10, 15}, should come up in the following queries on "b" attribute:
below(20),
above(14),
below(2)
but not in a search like:
above(16), below(0).
I hope I made myself clear.
Thanks in advance!
Change your bridge to storing same field multiple times, each with value a of the Integer list. So assuming your field is called myInt, you would store myInt = 1, myInt = 10 and myInt = 15, example code:
public class MyBridge implements FieldBridge {
public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
if (value instanceof List){
for(Object myInt:(List)value){
Field myIntField = new Field(name, myInt.toString(), luceneOptions.getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector());
myIntField.setBoost(luceneOptions.getBoost());
document.add(myIntField);
}
}
}
}
Alternately, you might be able to plugin some custom lucene Filter to do it, but Filters are a bit convoluted.

Categories

Resources