For mongodb 3.2 following query successfully worked.
db.user_log.aggregate([{ "$match" : { "user_id" : "1" , "page_id" : "678761252281073"}} , { "$sort" : { "meta_data.access_times" : -1}} , { "$group" : { "_id" : { "first_name" : "$meta_data.user_data.first_name" , "last_name" : "$meta_data.user_data.last_name" , "profile_pic" : "$meta_data.user_data.profile_pic" , "user_id" : "$user_id" , "star_value" : "$star_value" , "access.times" : "$meta_data.access_times"}}}])
Java code -
Aggregation aggregation = newAggregation(
match(Criteria.where("user_id").is("123")),
sort(Sort.Direction.DESC, "meta_data.access_times"),
group(Fields.fields().and("first_name", "$meta_data.user_data.first_name").and("last_name", "$meta_data.user_data.last_name").and("profile_pic", "$meta_data.user_data.profile_pic").and("user_id", "$user_id").and("star_value", "$star_value").and("access.times", "$meta_data.access_times"))
);
AggregationResults<UsersMongoResult> groupResults = mongoTemplate.aggregate(aggregation, "user_log", UsersMongoResult.class);
but after upgrading to 3.4 it occurs following exception
org.springframework.dao.InvalidDataAccessApiUsageException: Command
execution failed: Error [FieldPath field names may not contain '.'.]
what is the reason behind this and how do I fix the issue
?
Issue is access.times, It is a bad practice to have . in your fields as it collides with nested elements.
Related
I have a CosmosDb - MongoDb collection that I'm using purely as a key/value store for arbitrary data where the _id is the key for my collection.
When I run the query below:
globaldb:PRIMARY> db.FieldData.find({_id : new BinData(3, "xIAPpVWVkEaspHxRbLjaRA==")}).explain(true)
I get this result:
{
"_t" : "ExplainResponse",
"ok" : 1,
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "data.FieldData",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [ ]
},
"winningPlan" : {
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 106,
"totalKeysExamined" : 0,
"totalDocsExamined" : 3571,
"executionStages" : {
},
"allPlansExecution" : [ ]
},
"serverInfo" : #REMOVED#
}
Notice that the totalKeysExamined is 0 and the totalDocsExamined is 3571 and the query took over 106ms. If i run without .explain() it does find the document.
I would have expected this query to be lightning quick given that the _id field is automatically indexed as a unique primary key on the collection. As this collection grows in size, I only expect this problem to get worse.
I'm definitely not understanding something about the index and how it works here. Any help would be most appreciated.
Thanks!
I am working on Spring MVC with MongoDB.
I have added criteria for some fields with orOperator, Each Fields has value in database, but List returning is Empty.
criteriaQuery.addCriteria(Criteria.where("First_Name").is(docName.trim())
.orOperator(Criteria.where("Middle_Name").is(docName.trim())
.orOperator(Criteria.where("Last_Name").is(docName.trim()))));
Query printing in console is
Query: { "First_Name" : "ESTHER" , "$or" : [ { "Middle_Name" : "ESTHER" , "$or" : [ { "Last_Name" : "ESTHER"}]}]}, Fields: null, Sort: null
I tried the Like query, but that also results the same
criteriaQuery.addCriteria(Criteria.where("First_Name").regex(docName)
.orOperator(Criteria.where("Middle_Name").regex(docName))
.orOperator(Criteria.where("Last_Name").regex(docName)));
Mongo Query
db.doctor_details.find({ "$or" : {"First_Name" : { "$regex" : "ESTHER"} }, "$or" : [ { "Middle_Name" : { "$regex" : "ESTHER"} , "$or" : [ { "Last_Name" : { "$regex" : "ESTHER"}}]}]})
Help me to get the result, I dont know where my code goes wrong. Help is appreciated!
Thanks
As far as I remember in order to use orOperator you should do:
Query query = new Query(new Criteria().orOperator(criteriaV1,criteriaV2));
it is based on this answer
My mongo aggregation query is like this:
db.events.aggregate({
"$match" : { $or : [
{"event_state" : "live"},
{
$and: [
{"event_state" : "scheduled"},
{"schedule.start_time" : { "$gt" : ISODate("2016-12-15T14:06:00.000Z")}}
]
}
]
} },
{ "$sort" : { "schedule.start_time" : 1}} ,
{ "$project" : {
"registered_users_count" : { "$size" : [ "$registered_users"]} ,
"event_image" : 1 , "celebrity" : 1 , "name" : 1 , "category" : 1 ,
"schedule" : 1 , "online_moderator" : 1 , "offline_moderator" : 1 ,
"region" : 1 , "status" : 1 , "event_state" : 1 , "recorder_id" : 1 ,
"webcast_url" : 1 , "replay_url" : 1
}})
I tried something like below
Variant 1:
matchCondition = Aggregation.match(Criteria.where("event_state")
.is("scheduled").and("schedule.end_time").gt(d)
.orOperator(Criteria.where("event_state").is("live")));
Variant 2:
matchCondition = Aggregation.match(Criteria
.where("event_state")
.is("live")
.orOperator(
Criteria.where("event_state").is("scheduled")
.and("schedule.end_time").gt(d)));
Sort and Projection Conditions
sortCondition = Aggregation.sort(Sort.Direction.ASC,
"schedule.start_time");
AggregationOperation projectValues = Aggregation.project()
.and("registered_users").size().as("registered_users_count")
.and("event_image").as("event_image").and("celebrity")
.as("celebrity").and("name").as("name").and("category")
.as("category").and("schedule").as("schedule")
.and("online_moderator").as("online_moderator")
.and("offline_moderator").as("offline_moderator").and("region")
.as("region").and("status").as("status").and("event_state")
.as("event_state").and("recorder_id").as("recorder_id")
.and("webcast_url").as("webcast_url").and("replay_url")
.as("replay_url");
Aggregation aggrigation = Aggregation.newAggregation(matchCondition,
sortCondition, projectValues);
None of the Variant 1 and Variant 2 are producing desired condition. So how to achieve this?
Form the spring-data-mongo API documentation Criteria.OrOperators take multiple Criteria as argument to form a or operation like.
So the solution for this would be as follows:
Aggregation.match(
new Criteria().orOperator(
Criteria.where("event_state").is("scheduled").and("schedule.start_time").gt(d),
Criteria.where("event_state").is("live")
)
)
My MongoDB document looks something like as following:
{
"_class" : "com.foo.foo.FooClass",
"_id" : ObjectId("5441948f3004e65fbda72d9c"),
"actionType" : "LOGIN",
"actor" : "bolt",
"extraDataMap" : {
"workHours" : NumberLong(11869)
},
}
Where extraDataMap is a HashMap stored from the java code. I have to get all the documents where "actionType" is "Login", group on "actor" and sum all the "workHours" for those individual actors
If I do below query on MongoDB directly it works:
db.activityLog.aggregate([
{$match : { actionType : "LOGIN" }},
{$group : { "_id" : "$actor", "hours" : { "$sum" : "$extraDataMap.workHours" } } },
{$sort : {_id : 1}}
]);
But If I run the query from Java Code
TypedAggregation<ActivityLog> agg = Aggregation.newAggregation(ActivityLog.class,
buildCriteria(),
group("actor").sum("extraDataMap.workHours").as("hours"),
sort(Sort.Direction.ASC, MongoActivityLogRepository.DOCUMENT_ID_FIELD_NAME)
);
AggregationResults<ActivityLog> result = mongoOperations.aggregate(agg, ActivityLog.class);
List<ActivityLog> results = result.getMappedResults();
It gives below error:
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property work found for type java.lang.String
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:75)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:353)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:290)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:274)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:245)
at org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext.getReference(TypeBasedAggregationOperationContext.java:91)
at org.springframework.data.mongodb.core.aggregation.GroupOperation$Operation.getValue(GroupOperation.java:359)
at org.springframework.data.mongodb.core.aggregation.GroupOperation$Operation.toDBObject(GroupOperation.java:355)
at org.springframework.data.mongodb.core.aggregation.GroupOperation.toDBObject(GroupOperation.java:300)
at org.springframework.data.mongodb.core.aggregation.Aggregation.toDbObject(Aggregation.java:228)
at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1287)
at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1264)
at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1253)
Really appreciate all the prompt responses :)
I had the same problem than you and I found this solution
Instead of using TypedAggregation, use a plain Aggregation. This way, spring data won't perform a type checking.
It would be as follows:
Aggregation agg = Aggregation.newAggregation(
buildCriteria(),
group("actor").sum("extraDataMap.workHours").as("hours"),
sort(Sort.Direction.ASC, MongoActivityLogRepository.DOCUMENT_ID_FIELD_NAME)
);
List<ActivityLog> results = mongoOperations.aggregate(agg, mongoOperations.getCollectionName(ActivityLog.class), ActivityLog.class).getMappedResults();
See that I used a different mongoOperations.aggregate signature, because since we are not using a TypedAggregation, we have to indicate over which collection we are performing the aggregation.
I hope this helps you.
I'm trying to write a method that will check if a user_id is in the DB and then operate on the user_id.The portion of code that I'm stuck on is this:
DBObject query = new BasicDBObject(user_id,new BasicDBObject("$regex", true));
DBCursor result = dBcollection.find(query);
if (result.equals("true")) {
System.out.println("found");
//do stuff
}
else{
//do other stuff
}
My database is set up this way:
{ "_id" : { "$oid" : "53b4443ad121894f16ea3699"} , "user_id" : "1683777896" , "countries" : { "JA" : 1}}
{ "_id" : { "$oid" : "53b4443ad121894f16ea369a"} , "user_id" : "453121657" , "countries" : { "TU" : 1}}
I want to be able to query on the user_id and then operate on the record associated with that user_id but I can't figure out the correct syntax in java for the "if" statement.
Use this to query for the document with that user id:
DBObject query = new BasicDBObject("user_id", user_id);
Use this for the if statement to determine if the find actually found that user id:
if (result.hasNext())
If that doesn't go into the if statement, show us the code that gets the database and dBcollection, and make sure you are connecting to the right database and collection name.