Max value of a field with mongo-java-driver - java

I want to get max value of date field for whole collection 4programmers.
In mongo shell I can write:
db.getCollection("4programmers").aggregate([
{
$group:
{
_id: null,
max : {$max: "$date"}
}
}
])
and it returns a document with the date ISODate("2017-10-20T17:12:37.000+02:00") but when I write in java:
Date d = collection.aggregate(
Arrays.asList(
Aggregates.group("$date", Accumulators.max("maxx", "$date"))
)
).first().getDate("maxx");
System.out.println(d);
as a result I get: Fri Oct 20 00:44:50 CEST 2017
May something is wrong with first()?

First argument of Aggregates.group should be null instead of "$date" (it's actually _id: null).
So code should look like:
Date d = collection.aggregate(
Arrays.asList(
Aggregates.group(null, Accumulators.max("maxx", "$date"))
)
).first().getDate("maxx");
or you can do the same without Aggregates class:
collection.aggregate(asList(new Document("$group", new Document("_id", null)
.append("max", new Document("$max", "$date")))))
.first().getDate("max");

Related

Spock assert that list of objects have exact value in field

I'm not really familiar with Spock, so I will be appreciated for some hints.
I have a list of custom objects. I want to check that this list contains any number of objects where some of the fields have exact values.
For example, I have pojo and list that contains 100 records
public class CustomObject {
private int id;
private String name;
private double salary;
}
I want to check something like this :
List<CustomObject> objects = new ArrayList<>();
assert objects.contains(
object.id==100 && object.salary > 900
)
but "name" could be any.
Here is a little example of what you can do with Groovy collections.
BTW, I just copied the 500 most popular girls' names in Germany from a web site and used them as a data source.
package de.scrum_master.stackoverflow
import groovy.transform.ToString
import spock.lang.Specification
class ListMatchTest extends Specification {
static girlsNames = [
"Emma", "Hannah", "Mia", "Sofia", "Emilia", "Lina", "Anna", "Marie", "Mila", "Lea", "Leni", "Clara", "Lena", "Luisa", "Leonie", "Amelie", "Emily", "Johanna", "Ella", "Nele", "Sophie", "Charlotte", "Ida", "Lilly", "Laura", "Maja", "Mathilda", "Lara", "Frieda", "Lia", "Greta", "Lotta", "Sarah", "Melina", "Paula", "Julia", "Marlene", "Pia", "Alina", "Nora", "Elisa", "Victoria", "Mira", "Lisa", "Isabella", "Anni", "Juna", "Isabell", "Zoe", "Mara", "Luna", "Luise", "Finja", "Maria", "Josephine", "Pauline", "Romy", "Theresa", "Merle", "Antonia", "Elena", "Helena", "Paulina", "Eva", "Magdalena", "Jana", "Elli", "Katharina", "Emely", "Fiona", "Martha", "Lucy", "Stella", "Thea", "Annabell", "Amy", "Tilda", "Mina", "Elina", "Jasmin", "Carla", "Annika", "Alessia", "Jule", "Rosalie", "Malia", "Carlotta", "Elisabeth", "Maila", "Valentina", "Milena", "Nina", "Ronja", "Melissa", "Chiara", "Hailey", "Olivia", "Amelia", "Amalia", "Franziska", "Lotte", "Miriam", "Luana", "Zoey", "Linda", "Elif", "Leila", "Emmi", "Mariella", "Aaliyah", "Ela", "Selina", "Sina", "Anastasia", "Vanessa", "Tessa", "Helene", "Liana", "Aurelia", "Ava", "Lynn", "Kira", "Marleen", "Rosa", "Alma", "Carolin", "Diana", "Alicia", "Alexandra", "Jette", "Lene", "Lenja", "Marla", "Milla", "Freya", "Aurora", "Elsa", "Amira", "Malina", "Aylin", "Lucia", "Ylvi", "Enna", "Lana", "Carolina", "Jara", "Liv", "Amina", "Joleen", "Elise", "Liya", "Leticia", "Mathea", "Giulia", "Jolina", "Rebecca", "Alisa", "Edda", "Evelyn", "Laila", "Mona", "Svea", "Celine", "Julie", "Liliana", "Milana", "Vivien", "Tabea", "Cataleya", "Talia", "Livia", "Daria", "Noemi", "Alissa", "Ariana", "Annalena", "Miray", "Carina", "Leana", "Melia", "Veronika", "Melek", "Zeynep", "Bella", "Alice", "Maira", "Celina", "Annelie", "Henriette", "Jonna", "Christina", "Fabienne", "Nela", "Amilia", "Linea", "Nelly", "Felicitas", "Medina", "Michelle", "Natalie", "Samira", "Anne", "Alena", "Angelina", "Leona", "Rieke", "Alea", "Dana", "Larissa", "Selma", "Valerie", "Xenia", "Lou", "Marina", "Tamara", "Marlena", "Heidi", "Lorena", "Helen", "Hermine", "Joline", "Malea", "Dilara", "Enie", "Azra", "Defne", "Ina", "Kate", "Meryem", "Nisa", "Josie", "Madita", "Florentine", "Mariam", "Elea", "Eliana", "Hedi", "Nika", "Enya", "Valeria", "Eleni", "Fenja", "Holly", "Levke", "Malin", "Flora", "Leandra", "Palina", "Tamina", "Ayla", "Leia", "Lieselotte", "Hira", "Jessika", "Nala", "Nicole", "Alia", "Elin", "Malou", "Alexa", "Aleyna", "Estelle", "Kim", "Cara", "Melody", "Esila", "Josefin", "Sunny", "Felicia", "Käthe", "Liesbeth", "Lilia", "Ruby", "Selin", "Smilla", "Felina", "Mailin", "Adriana", "Eleonora", "Fritzi", "Kaja", "Lola", "Fatima", "Juliana", "Tara", "Madlen", "Samantha", "Delia", "Lilith", "Naila", "Aria", "Arina", "Lilian", "Miley", "Tuana", "Amara", "Asya", "Eda", "Hilda", "Jolie", "Kimberly", "Viola", "Alva", "Ellen", "Marit", "Fine", "Liara", "Mathilde", "Melisa", "Felia", "Liz", "Talea", "Arya", "Cecilia", "Clea", "Esma", "Janne", "Sonja", "Adelina", "Alexia", "Helin", "Melinda", "Wilma", "Gloria", "Grace", "Josephina", "Lenia", "Mary", "Patricia", "Amanda", "Esther", "Friederike", "Juliane", "Leonora", "Marieke", "Naomi", "Zara", "Dalia", "Malena", "Melanie", "Natalia", "Romina", "Tina", "Alya", "Hedda", "Joana", "Maike", "Philippa", "Claire", "Enni", "Eylül", "Inga", "Luzi", "Nila", "Shirin", "Soraya", "Alara", "Jasmina", "Maileen", "Marisa", "Nike", "Philine", "Salome", "Zehra", "Zuzanna", "Alisha", "Anja", "Ashley", "Bianca", "Ecrin", "Erna", "Evelina", "Charlotta", "Cleo", "Eliza", "Feline", "Jella", "Jill", "Madeleine", "Naemi", "Ria", "Sena", "Skadi", "Anisa", "Elaine", "Eleanor", "Ilayda", "Janina", "Judith", "Katja", "Lydia", "Melis", "Neyla", "Tiana", "Ada", "Alica", "Anouk", "Evi", "Henrieke", "Verena", "Abby", "Cassandra", "Ceylin", "Eslem", "Ivy", "Janna", "Lani", "Mieke", "Mika", "Annemarie", "Iva", "Jenna", "Maren", "Nadia", "Penelope", "Violetta", "Betty", "Elis", "Giuliana", "Irma", "Jolien", "Lavin", "Rita", "Adele", "Alessa", "Hazal", "Jamila", "Jolene", "Julina", "Kiana", "Margarete", "Maxi", "Meta", "Noelia", "Rahel", "Svenja", "Almira", "Anita", "Ann", "Asmin", "Elissa", "Erika", "Lilou", "Line", "Runa", "Ruth", "Saskia", "Simay", "Stina", "Ylva", "Zümra", "Ceyda", "Cora", "Elenor", "Jennifer", "Joy", "Leonore", "Liyana", "Malak", "Megan", "Minna", "Selena", "Sila", "Abigail", "Arin", "Clarissa", "Darina", "Femke", "Frederike", "Lorin", "Luca", "Luzia", "Nia", "Phoebe", "Rafaela", "Rana", "Charlie", "Debora", "Erva", "Esra", "Franka", "Jona", "Lisann", "Marielle", "Nelia", "Nour", "Nova", "Sandra", "Stefanie", "Theresia", "Toni", "Vera", "Yaren", "Amber", "Cheyenne", "Chloe", "Daniela", "Florentina", "Gabriela", "Hanne"
]
#ToString(includePackage = false)
static class Employee {
int id
String name
double salary
}
static lastId = 0
static employees = girlsNames.collect {
new Employee(id: ++lastId, name: it, salary: 100 * (lastId % 13 + 1))
}
def "Employee with ID 100 and salary > 900 exists"() {
expect:
employees.any { it.id == 100 && it.salary > 900 }
}
def "There are at least 70 employees with salaries >= 1111"() {
expect:
employees.count { it.salary >= 1111 } >= 70
}
def "Employee Marie is unique"() {
expect:
employees.count { it.name == "Marie" } == 1
}
def "Field 'id' is a unique key"() {
expect:
employees.collect { it.id }.toSet().size() == employees.size()
}
def "Field 'salary' is not unique"() {
expect:
employees.collect { it.salary }.toSet().size() != employees.size()
}
}
P.S.: For very large data sets, especially when reading them from some file or database, you really might want to use Java streams as suggested by David Conrad, especially if you just want to find the first n elements matching certain criteria, utilising the stream's laziness and avoiding to read everything even though you already know what you need to know for your program logic.
You can use Groovy's every for that:
List<CustomObject> objects = new ArrayList<>()
assert objects.every { it.id==100 && it.salary > 900 }
This will only return true, if the closure returns true for all elements in the list.
For huge lists this will lead to outputs which are hard to read though. Therefore I prefer findAll in such cases:
List<CustomObject> objects = new ArrayList<>()
assert objects.findAll { it.id!=100 && it.salary <= 900 }.empty
This code will output the unexpected elements separately, so the error is easier to detect.

How to use DateTime Object split Interval Object

I have an Interval object:
Interval firstInterval =
new Interval(new DateTime(2017,06,26,07,55,30),new DateTime(2017,06,26,22,55,30));
and:
DateTime nightToDay = new DateTime(2017, 06, 26, 8, 0, 0);
DateTime dayToNight = new DateTime(2017, 06, 26, 22, 0, 0);
I want to get a Interval[]:
[
[2017-06-26 07:55:30 ~ 2017-06-26 08:00:00],
[2017-06-26 08:00:00 ~ 2017-06-26 22:00:00],
[2017-06-26 22:00:00 ~ 2017-06-26 22:55:30]
]
Of course, these parameters aren't fixed, and it is just an example.
Assuming that your general case is:
have a first interval with start and end
receives a nightToDay and dayToNight dates
output must contain 3 intervals:
start to nightToDay
nightToDay to dayToNight
dayToNight to end
And for each case above, you also need to check if the start of the interval is before the end.
If that's what you need, just do:
List<Interval> list = new ArrayList<Interval>();
if (firstInterval.getStart().isBefore(nightToDay)) {
list.add(new Interval(firstInterval.getStart(), nightToDay));
}
if (nightToDay.isBefore(dayToNight)) {
list.add(new Interval(nightToDay, dayToNight));
}
if (dayToNight.isBefore(firstInterval.getEnd())) {
list.add(new Interval(dayToNight, firstInterval.getEnd()));
}
The list will contain all the Interval objects you need.
If you need an array, it's easy to convert the list:
Interval[] intervals = new Interval[list.size()];
intervals = list.toArray(intervals);
The intervals array will have all the intervals created.

How to return a list contains Object in sqlalchemy in python, is similar to List<OrderInfo> in java

i want to get a list which contains entire OrderInfo Object, for example, if i do this, it is result which the result i want to.
def find_all(self):
result_list = []
orderDao = DaoUtil.DaoGeneric()
session = orderDao.getSession()
try:
for row in session.query(OrderInfo).all():
result_list.append({
'id':row.id,
'name': row.name,
'age': row.age,
'create_time': row.create_time.strftime("%Y-%m-%d %H:%M:%S"),
'update_time': row.update_time.strftime("%Y-%m-%d %H:%M:%S"),
'version': row.version
})
session.commit()
except Exception, e:
print e
session.rollback()
return result_list
but i want to a list which contains OrderInfo object from the query, because the result which the query return have other columns (the simple list of all DeclarativeBase's instances.) except OrderInfo{id,name,age,create_time,update_time,version}, the query do not return OrderInfo object directly. the following which i want to:
def find_all(self):
result_list = []
orderDao = DaoUtil.DaoGeneric()
session = orderDao.getSession()
try:
for row in session.query(OrderInfo).all():
result_list.append(row.orderInfo) // if the row has a property for orderInfo Object, because the result which java can achieve , the example for java is : List<OrderInfo> orderList = session.query(); please help to achieve it
session.commit()
except Exception, e:
print e
session.rollback()
return result_list
beacause i use sqlalchemy in python just now, i am not very sure. How to get a list which contains OrderInfo Object from query in sqlalchemy
#univerio
for row in session.query(OrderInfo).all():
the line of variable 's row which includes the following column:
_decl_class_registry,
_sa_class_manager,
_sa_instance_state,
metadata,
query,
id,
name,
age,
create_time,
update_time ,
version
only this (OrderInfo{id, name, age, create_time,update_time,version}) is what i want to get, other columns which i do not want to get.
OrderInfo:
from sqlalchemy import Column, Integer, String, Date, DateTime
from sqlalchemy.ext.declarative import declarative_base
Base=declarative_base()
class OrderInfo(Base):
__tablename__ = 'order_info'
# __table__ = 'order_info'
id = Column(Integer, primary_key=True)
name = Column(String(100))
age = Column(Integer)
create_time = Column(Date)
update_time = Column(Date)
version = Column(Integer)
#univerio, i write here because the comments has limit of words, it achieve this result, like this:
for row in session.query(OrderInfo).all():
result_list.append({
'id':row.id,
'name': row.name,
'age': row.age,
'create_time': row.create_time.strftime("%Y-%m-%d %H:%M:%S"),
'update_time': row.update_time.strftime("%Y-%m-%d %H:%M:%S"),
'version': row.version
})
the OrderInfo has very few columns, if the OrderInfo object has more than serveral hundred columns, but it will take a long time, so i want find the result which can simple achieve this function that is similar to List in Java
#univerio,
i find the answer which i want to get:
def find_all(self):
result_list = []
orderDao = DaoUtil.DaoGeneric()
session = orderDao.getSession()
try:
for row in session.query(OrderInfo).all():
result_list.append(DictUtil.object_as_dict(row))
session.commit()
except Exception, e:
print e
session.rollback()
return result_list
def object_as_dict(obj):
result = {instance.key: getattr(obj, instance.key) for instance in inspect(obj).mapper.column_attrs}
print result
return result
output :
[
{'updateTime': datetime.datetime(2017, 6, 15, 13, 56, 16), 'bankName': u'ICBC', 'bankNo': u'6228480666622220011', 'createTime': datetime.datetime(2017, 6, 15, 13, 56, 16), u'version': 0, u'id': 1},
{'updateTime': datetime.datetime(2017, 6, 15, 13, 57, 40), 'bankName': u'ICBC', 'bankNo': u'6228480666622220011', 'createTime': datetime.datetime(2017, 6, 15, 13, 57, 40), u'version': 0, u'id': 2},
{'updateTime': datetime.datetime(2017, 6, 15, 13, 58), 'bankName': u'ICBC', 'bankNo': u'6228480666622220011', 'createTime': datetime.datetime(2017, 6, 15, 13, 58), u'version': 0, u'id': 3}
]

How to resolve java.lang.NullPointerException in scala?

assume part of my code is like as:-
where doc is List[Document] that contains stu_name and roll_number
sometimes stu_name and roll_name may be null.
I used Try to avoid null Pointer exception in first two lines.
but why I m getting again Null Pointer exception in "val myRow".
val name= Try {Option.apply(doc.getFieldValue("stu_name"))}.getOrElse(null)
val rollNumber ={Option.apply(doc.getFieldValue("roll_number"))}.getOrElse(null)
val myRow = (
doc.getFieldValue("ID").asInstanceOf[Int] //can't be null
name.getOrElse(null).toString, //NullPointerException
rollNumber.getOrElse(null).asInstanceOf[Int] //NullPointerException
)
.....
.....
I m getting following error:
[2016-01-14 22:40:16,896] WARN o.a.s.s.TaskSetManager [] [akka://JobServer/user/context-supervisor/demeter] - Lost task 0.0 in stage 0.0 (TID 0, 10.29.23.136): java.lang.NullPointerException
at com.test.events.Monitoring$$anonfun$geteventTableReplicateDayFunc$1.apply(Monitoring.scala:75)
at com.test.events.Monitoring$$anonfun$geteventTableReplicateDayFunc$1.apply(Monitoring.scala:57)
at com.test.events.Monitoring$$anonfun$27.apply(Monitoring.scala:104)
at com.test.events.Monitoring$$anonfun$27.apply(Monitoring.scala:104)
I tried in console following but did not see any error:
scala> val a = Try (Option.apply("atar")).getOrElse(null)
a: Option[String] = Some(atar)
scala> a.getOrElse(null)
res16: String = atar
scala> val a = Try (Option.apply(null)).getOrElse(null)
a: Option[Null] = None
scala> a.getOrElse(null)
res17: Null = null
This is all wrong. By using getOrElse(null) you are basically removing all advantages to using an Option to begin with. Plus, generating much more complexity than needed.
You need to define what you will do if the values are null. This just keeps them as Options (None on null input):
val myRow = (
doc.getFieldValue("ID").toInt, // Fails if null
Option(doc.getFieldValue("stu_name")), // `None` if null
Option(doc.getFieldValue("roll_number")).map(_.toInt) // `None` if null
)
Or use default values:
val myRow = (
doc.getFieldValue("ID").toInt,
Option(doc.getFieldValue("stu_name")).getOrElse("default"),
Option(doc.getFieldValue("roll_number")).map(_.toInt).getOrElse(0)
)

Date interval sum and subtraction in Java

I'm looking for a library or helper class in Java that would allow me to perform date interval sum and subtractions.
For example, lets's say I have the following date intervals:
A = ["2015-01-01 00:00", "2015-01-20 00:00"]
B = ["2015-01-05 00:00", "2015-01-10 00:00"]
C = ["2015-01-11 00:00", "2015-01-14 00:00"]
D = ["2015-01-19 00:00", "2015-01-25 00:00"]
1 A 20
|----------------------------------|
|---------| |----------| |------------|
5 B 10 11 C 14 19 D 25
And let's say I'd like to calculate the following:
A - B - C + D = { ["2015-01-01 00:00", "2015-01-05 00:00"[,
]"2015-01-10 00:00", "2015-01-11 00:00"[,
]"2015-01-14 00:00", "2015-01-25 00:00"] }
1 5 10 11 14 25
|---| |---| |----------------|
I know I can build my own logic using pure Java, but I'd rather not reinvent the wheel...
I was looking into Joda-Time, but I couldn't figure out how to perform such operations using it.
Thanks a lot!
I found exactly what I needed: Ranges, from the guava-libraries.
Works like this:
Range<Date> a = Range.closed(
new GregorianCalendar(2015, 0, 1).getTime(),
new GregorianCalendar(2015, 0, 20).getTime());
Range<Date> b = Range.closed(
new GregorianCalendar(2015, 0, 5).getTime(),
new GregorianCalendar(2015, 0, 10).getTime());
Range<Date> c = Range.closed(
new GregorianCalendar(2015, 0, 11).getTime(),
new GregorianCalendar(2015, 0, 14).getTime());
Range<Date> d = Range.closed(
new GregorianCalendar(2015, 0, 19).getTime(),
new GregorianCalendar(2015, 0, 25).getTime());
RangeSet<Date> result = TreeRangeSet.create();
result.add(a);
result.remove(b);
result.remove(c);
result.add(d);
System.out.println(result);
The code above prints:
[
[Thu Jan 01 00:00:00 BRST 2015‥Mon Jan 05 00:00:00 BRST 2015),
(Sat Jan 10 00:00:00 BRST 2015‥Sun Jan 11 00:00:00 BRST 2015),
(Wed Jan 14 00:00:00 BRST 2015‥Sun Jan 25 00:00:00 BRST 2015]
]
I think it can be done basically using Joda-Time with some custom code. It is assumed that A is the Interval which all other intervals should relate to.
While this code should give the expected results (and should work for different values accordingly) I highly suggest testing it with very different data, especially for the three cases a) an interval not intersecting A at all, b) intersecting A at the beginning and c) an interval which itself intersects B or C or D.
So despite this, it might help for further tests.
Interval a = new Interval(Instant.parse("2015-01-01T00:00Z"), Instant.parse("2015-01-20T00:00Z"));
List<Interval> l = Arrays.asList(
/* b */ new Interval(Instant.parse("2015-01-05T00:00Z"), Instant.parse("2015-01-10T00:00Z")),
/* c */ new Interval(Instant.parse("2015-01-11T00:00Z"), Instant.parse("2015-01-14T00:00Z")),
/* d */ new Interval(Instant.parse("2015-01-19T00:00Z"), Instant.parse("2015-01-25T00:00Z"))
);
List<Interval> results = new ArrayList<Interval>();
for (Interval i : l) {
if (a.contains(i)) {
// if i is completely inside a, then calculate the first part and the remaining part
// whereas the first part will be added to the result
Interval firstPart = new Interval(a.getStart(), i.getStart());
results.add(firstPart);
// followed by i itself (skipped)
// part after i, inside a
Interval remainingPart = new Interval(i.getEnd(), a.getEnd());
a = remainingPart;
} else if (i.overlaps(a)) {
// if the intervals only overlap, then we take the earliest beginning and the latest ending as a result part
DateTime overlapMin = (a.getStart().isBefore(i.getStart())) ? a.getStart() : i.getStart();
DateTime overlapMax = (a.getEnd().isAfter(i.getEnd())) ? a.getEnd() : i.getEnd();
Interval overlapAndBothParts = new Interval(overlapMin, overlapMax);
results.add(overlapAndBothParts);
// if the checked interval i is at the beginning, then a will become the part after this "overlap"
if (i.getStartMillis() < a.getStartMillis()) {
Interval whatsLeft = new Interval(i.getEndMillis(), a.getEndMillis());
a = whatsLeft;
}
}
}
// print result
for (Interval i : results) {
System.out.println("result part: " + i);
}

Categories

Resources