Spring data mongo query to aggregate(Distinct) with pagination - java

Given we have following documents in database
{id:0, SID:0, STATUS:"UNDONE", UID:1, AT:122}
{id:1, SID:1, STATUS:"DONE", UID:1, AT:123}
{id:2, SID:1, STATUS:"DONE", UID:2, AT:124}
{id:3, SID:2, STATUS:"PEN", UID:3, AT:125}
{id:4, SID:2, STATUS:"PEN", UID:4, AT:126}
{id:5, SID:3, STATUS:"DONE", UID:5, AT:127}
{id:6, SID:4, STATUS:"DONE", UID:6, AT:128}
I'm trying to get write a query using spring data mongodb to skip 'm' distinct SID and get next 'n' distinct SID (Sorted by AT field) matching the filter and return documents corresponding to those SIDs.
For this example m = 1 and n = 2 would return these documents
{id:3, SID:2, STATUS:"PEN", UID:3, AT:125}
{id:4, SID:2, STATUS:"PEN", UID:4, AT:126}
{id:5, SID:3, STATUS:"DONE", UID:5, AT:127}
So far I've managed to write this.
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.project("STATUS", "AT", "SID"),
Aggregation.match(Criteria.where("STATUS").in("DONE", "PEN")),
Aggregation.sort(Sort.Direction.DESC, "AT"),
Aggregation.group("SID"),
Aggregation.skip(skip),
Aggregation.limit(limit));
AggregationResults<Map> results = mongoOperations.aggregate(aggregation, MyClass.class, Map.class);
List<String> SIDs = results.getMappedResults().stream().map(it -> it.get("_id").toString()).collect(Collectors.toList());
Query query = new Query();
query.addCriteria(Criteria.where("SID").in(SIDs));
return mongoOperations.find(query, MyClass.class);
This is returning unpredictable results ie every call returns different results and therefore not sorted as intended.
What am I missing here?
I've a feeling the sort stage in pipeline is incorrectly placed.

Related

Java MongoTemplate: aggregation using String criteria

Context
I need to rewrite some code previoulsy with Jongo but using Springframework MongoDb. Previous code was:
eventsCollection
.aggregate("{$match:" + query + "}")
.and("{$group: {_id: '$domain', domain: {$first: '$domain'}, codes: {$push: '$code'}}}")
.and("{$project : { _id: 0, domain: 1 , codes: 1 } }")
.as(DomainCodes.class);
where eventsCollection is Jongo MongoCollection, and query is a String containing with criteria.
Problem
New code must probably look like :
Aggregation myAggregation = Aggregation.newAggregation(
Aggregation.match(/* something here */),
Aggregation.group("domain").first("domain").as("domain").push("code").as("codes")
);
mongoTemplate.aggregate(myAggregation, "collectionName", DomainCodes.class);
but I don't find a way to create match criteria using String (similare as BasicQuery that can take a query as String for argument)
Question
In order to change as little code as possible, is there anyway to use query String as in Jongo ?
Thank you,

Azure cosmos Db Criteria query with subdocuments - java spring boot

I'm new to azure cosmos db. i'm trying to read items from container in my spring boot application. i'm using cosmos template with criteria. lets say i have a document like this
{
"stop_id": 70021,
"stop_name": "CALTRAIN - 22ND ST STATION",
"stop_lat": 37.757692,
"stop_lon": -122.392318,
"zone_id": 3329,
"trip": [{
"trip_id": "RTD8997283",
"arrival_time": "05:40:00",
"departure_time": "05:40:00",
"stop_id": 70021,
"stop_sequence": 1
}, {
"trip_id": "RTD8997283",
"arrival_time": "05:52:00",
"departure_time": "05:52:00",
"stop_id": 70021,
"stop_sequence": 2
}]
}
if i want to fetch based on stop id, i can add criteria for stop id like this
Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "stop_id", Collections.singletonList("70021"), Part.IgnoreCaseType.ALWAYS);
CosmosQuery cosmosQuery = new CosmosQuery(criteria).with(Sort.unsorted());
Iterable<StopInfo> items = cosmosTemplate.find(cosmosQuery, StopInfo.class, "myContainer");
But if i want to add criteria for trip id, how can i do it?
This way you can search from array in cosmos using criteria
Map map = new HashMap();
map.put("trip_id","RTD8997283");
Criteria criteria = Criteria.getInstance(CriteriaType.ARRAY_CONTAINS, "trip", Collections.singletonList(map), Part.IgnoreCaseType.ALWAYS);
CosmosQuery cosmosQuery = new CosmosQuery(criteria).with(Sort.unsorted());
Iterable<StopInfo> items = cosmosTemplate.find(cosmosQuery, StopInfo.class, "myContainer");

How to add a sort query to my StructuredQueryBuilder before talking to Marklogic

I am trying to add a sort/ordering query.
At my java:
StructuredQueryBuilder qb = new StructuredQueryBuilder();
QueryDefinition queryDef = qb.and(qb.value(qb.jsonProperty("status"), "Active"));
SearchHandle resultsHandle = new SearchHandle();
queryManager.setPageLength(PAGE_SIZE_TEN);
int start = PAGE_SIZE_TEN * (pageNumber - 1) + 1;
queryManager.search(queryDef, resultsHandle, start);
The above will return the resultsHandle with 10 json files found for each page specified for the variable "start", with status "Active".
My question is how do I include a sorting query like maybe something along the line of the following:
QueryDefinition queryDef = qb.and(qb.value(qb.jsonProperty("status"), "Active"),
qb.sort?(qb.jsonProperty("dateCreated"));
I want it to get me the 1st 10 json files in order of latest date. It is too late to do a Comparator after getting the result, as the result returns a random 10 json files not in any particular order.
A few samples of the json files will look as such:
1.json
[
{
"id":"1",
"dateCreated":"2017-10-01 12:00:00",
"status":"Active"
"body":"This is a test"
}
]
2.json
[
{
"id":"2",
"dateCreated":"2017-10-02 12:00:00",
"status":"Active"
"body":"This is a test 2"
}
]
I realized there's a enum StructuredQueryBuilder.Ordering, how do I use it?
StructuredQueryBuilder.Ordering is specifically for use with near-query and is unrelated to what you want to do. You need to use query options to define a sort order for your search results. See the sort-order query option:
http://docs.marklogic.com/guide/search-dev/appendixa#id_44212
Options can be pre-defined and installed on MarkLogic and then referenced in your search, or you can define them at runtime and combine them with your structured query in a combined query.
Predefined: http://docs.marklogic.com/guide/java/query-options#chapter
Dynamic: http://docs.marklogic.com/guide/java/searches#id_76144

MongoDB - Query by 2dsphere returns zero results

I wish to obtain a list of documents from a MongoDB collection by geospatial index. I have indexed the collection by 2dsphere
db.getCollection("Info").ensureIndex(new BasicDBObject("location", "2dsphere"), "geospatial");
A document in the Info collection look like this
{ "_id" : ObjectId("52631572fe38203a7388ebb5"), "location" : { "type" : "Point", "coordinates" : [ 144.6682361, -37.8978304 ] }
When I query the Info collection by the coordinates [ 144.6682361, -37.8978304 ], I am getting zero collections returned.
I am using JAVA API to perform the action. My JAVA code is below
DBCollection coll1=db.getCollection("Info");
BasicDBObject locQuery = new BasicDBObject();
locQuery.put("near", loc);
locQuery.append("maxDistance", 3000);
locCursor =coll1.find(locQuery);
System.out.println("LOCCURSOR"+locCursor.size());
The locCursor.size() returns always 0. Not sure where I am missing. At the same time, I am not getting any errors. It just gives me 0 documents returned. Any ideas Mongo users? Thanks for your time and help.
You can directly pass the value of your co-ordinates into your query:
double lat_lng_values[] = {144.6682361, -37.8978304};
BasicDBObject geo = new BasicDBObject("$geometry", new BasicDBObject("type","Point").append("coordinates",lat_lng_values));
BasicDBObject filter = new BasicDBObject("$near", geo);
filter.put("$maxDistance", 3000);
BasicDBObject locQuery = new BasicDBObject("location", filter);
System.out.println(locQuery);

Hibernate search with Criteria restriction returning incorrect count

The result list is perfect but the getResultSize() is incorrect.
I've knocked up some code to illustrate.
Criteria criteria2 = this.getSession().createCriteria(Film.class);
Criterion genre = Restrictions.eq("genreAlias.genreName", details.getSearch().getGenreName());
criteria2.createAlias("genres", "genreAlias", CriteriaSpecification.INNER_JOIN);
criteria2.add(genre);
criteria2.setMaxResults(details.getMaxRows())
.setFirstResult(details.getStartResult());
FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search.createFullTextEntityManager(entityManager);
org.apache.lucene.queryParser.QueryParser parser2 = new QueryParser("title", new StopAnalyzer() );
org.apache.lucene.search.Query luceneQuery2 = parser2.parse( "title:"+details.getSearch()");
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery( luceneQuery2, Film.class);
fullTextQuery.setCriteriaQuery(criteria2);
fullTextQuery.getResultList()); // Returns the correctly filtered list
fullTextQuery.getResultSize()); // Returns the retsult size without the genre resrtiction
From http://docs.jboss.org/hibernate/search/3.3/api/org/hibernate/search/jpa/FullTextQuery.html
int getResultSize()
Returns the number of hits for this search Caution: The number of results might be slightly different from getResultList().size() because getResultList() may be not in sync with the database at the time of query.
You should try to use some of the more specialized queries like this one:
Query query = new FuzzyQuery(new Term("title", q));
FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(query, Film.class);
int filmCount = fullTextQuery.getResultSize();
and this is how you do pagination requests (I'm guessing you have improperly implemented your paggination):
FullTextQuery hits = Search.getFullTextSession(getSession()).createFullTextQuery(query, Film.class)
.setFirstResult((pageNumber - 1) * perPageItems).setMaxResults(perPageItems);
The above works for me every time. You should keep in mind that the result of getResultSize() more of estimate. I use pagination a lot and I have experienced the number changing between pages. So you should say "about xxxx" results.

Categories

Resources