Polishing a mongodb query - java

This is my current query: Using Java+mongoDB
{
BasicDBObject select = new BasicDBObject();
select.put("info.name.fn", 1);
DBCursor cursor = collection.find(new BasicDBObject(), select);
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
It gives an output as:
{ "_id" : { "$oid" : "123"} , "info" : { "name" : { "fn" : "foo"}}}
{ "_id" : { "$oid" : "123"} , "info" : { "name" : { "fn" : "bar"}}}
{ "_id" : { "$oid" : "123"} , "info" : { "name" : { "fn" : "baz"}}}
_ids changed to accommodate the output. My question is, what query do I give to get the output as:
foo
bar
baz
Is it even possible? Or does every query always return it in the above format? I cant run a distinct() because there are duplicate names.
Thanks.

The minimal query result you can get is the one you show above.
You do not have to print all of that, though.
System.out.println(cursor.next().get("info").get("name").get("fn"));

Related

mongoTemplate returning unformatted object

I have following aggregation query method:-
public List<String> fetchRelativeIds(String externalId) {
ProjectionOperation projectionOperation = project().and("ancestors._id")
.concatArrays("descendants._id").as("weNeedRelations").andInclude("_id");
MatchOperation filterByIds = Aggregation.match(new Criteria("externalIds.fenergo").is(externalId));
Aggregation aggregation = newAggregation(filterByIds, projectionOperation);
return mongoTemplate.aggregate(aggregation, Master.class.getSimpleName(), String.class).getMappedResults();
}
This gives me output as below:-
{ "_id" : { "$oid" : "5aafb705f3fabe7c915bca14"} , "weNeedRelations" : [ { "$oid" : "5aafb718f3fabe7c915bca1f"} , { "$oid" : "5aafb719f3fabe7c915bca23"} , { "$oid" : "5aafb6fbf3fabe7c915bca10"}]}
I just want the $oid value part as string nothing else. E.g.
{ "_id" : "5aafb705f3fabe7c915bca14" , "weNeedRelations" : [ "5aafb718f3fabe7c915bca1f" , "5aafb719f3fabe7c915bca23", "5aafb6fbf3fabe7c915bca10"]}
How could I do that?

How can I retrieve all the values in a column in mongo db into a ArrayList?

This is the values of my data stored in mongo db. How am I able to retrieve all the data of "HomeTown" and store it all into a list? My list would contain AA, AA, BB, BB, etc... I want to use that array list to create a for loop of each Hometown.
Sample mongo data
[{ "_id" : { "$oid" : "4ceb753a70fdf877ef5113ca"} , "HomeTown" : "AA" ,
"PhoneNumber" : { "CustName" : "xxx" , "Number" : "3403290"},
"MobileNumber" : { "CustName" : "yyy" , "Number" : "9323304302"}}]
[{ "_id" : { "$oid" : "4ceb753a70fdf877ef5113ca"} , "HomeTown" : "AA" ,
"PhoneNumber" : { "CustName" : "xxx" , "Number" : "3403290"},
"MobileNumber" : { "CustName" : "yyy" , "Number" : "9323304302"}}]
[{ "_id" : { "$oid" : "4ceb753a70fdf877ef5113ca"} , "HomeTown" : "BB" ,
"PhoneNumber" : { "CustName" : "xxx" , "Number" : "3403290"},
"MobileNumber" : { "CustName" : "yyy" , "Number" : "9323304302"}}]
[{ "_id" : { "$oid" : "4ceb753a70fdf877ef5113ca"} , "HomeTown" : "BB" ,
"PhoneNumber" : { "CustName" : "xxx" , "Number" : "3403290"},
"MobileNumber" : { "CustName" : "yyy" , "Number" : "9323304302"}}]
How can I get all of the values of "HomeTown" in Java into an array? I am trying to create a for loop with the HomeTown Names. I am currently using mongodb dependency through Spring boot. I am not sure how would I implement mongodb into my java to use mongo db.
Attempt/Problem
I was able to retrieve mongodb values in a list using the following code. I am trying to convert this list to a arraylist.
public List<AppPortModel> getAppPortList() {
List<ApServerModel> objLst = mongoOperations.findAll(ApServerModel.class);
String[] apServerArray = new String[objLst.size()];
for(int i = 0; i < objLst.size(); i++) {
apServerArray[i] = objLst.get(i);
}
Error on objLst.get(i)
Type mismatch: cannot convert from ApServerModel to String
Attempt #2 Following Sagar Example
#Autowired
MongoOperations mongoOperations;
MongoCollection<ApServerModel> myCollection = **mongoOperations.getCollection("apAllCustomer");**
List<ApServerModel> result = myCollection.find().into(new ArrayList<>());
Error on mongoOperations.getCollection
Type mismatch: cannot convert from DBCollection to MongoCollection<ApServerModel>
Looks like you're using mongo 3.x driver.You'll need to use something like this.
MongoClient mongoClient = new MongoClient();
MongoDatabase db = mongoClient.getDatabase("mkoydb");
MongoCollection<Document> myCollection = db.getCollection("apAllCustomer");
List<Document> result = myCollection.find().into(new ArrayList<>());
Fix for Attempt 1:
public List<AppPortModel> getAppPortList() {
List<ApServerModel> objLst = mongoOperations.findAll(ApServerModel.class);
String[] apServerArray = new String[objLst.size()];
for(int i = 0; i < objLst.size(); i++) {
apServerArray[i] = objLst.get(i).getHomeTown();
}
Fix for Attempt 2:
DBCollection dbCollection = mongoOperations.findAll(AppServreModel.class, "apAllCustomer");
You can call toArray() which, intuitively, returns a List<DBObject>.
List<DBObject> myList = null;
DBCursor myCursor=myCollection.find(new BasicDBObject(),"HomeTown");
myList = myCursor.toArray();
if you are using java driver with version 3.0 and above you can also do
collection.find().projection(Projections.include("HomeTown"));
You can use projection to retrieve only required fields.
db.apAllCustomer.find( ..., { HomeTown: 1 } );
In Java it depends on the API you use. See this for Spring Data:
SpringData MongoDB Using projection
MongoDB-Java:
Restrict fields in Result

Spring Data Mongo Template - Counting an array

Mongo document:
{
"_id" : "1",
"array" : [
{
"item" : "item"
},
{
"item" : "item"
}
]
}
My mongo shell query looks like so:
db.getCollection('collectionName').aggregate(
{$match: { _id: "1"}},
{$project: { count: { $size:"$array" }}}
)
Is there anyway to implement this using the Mongo Template from Spring?
So far I have this:
MatchOperation match = new MatchOperation(Criteria.where("_id").is("1"));
ProjectionOperation project = new ProjectionOperation();
Aggregation aggregate = Aggregation.newAggregation(match, project);
mongoTemplate.aggregate(aggregate, collectionName, Integer.class);
I think I am only missing the project logic but I'm not sure if it is possible to do $size or equivalent here.
It's quite possible, the $size operator is supported (see DATAMONGO-979 and its implementation here). Your implementation could follow this example:
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
Aggregation agg = new Aggregation(
match(where("_id").is("1")), //
project() //
.and("array") //
.size() //
.as("count")
);
AggregationResults<IntegerCount> results = mongoTemplate.aggregate(
agg, collectionName, Integer.class
);
List<IntegerCount> intCount = results.getMappedResults();
Please find below the sample code. You can change it accordingly for your requirement with collection name, collection name class and array field name.
MatchOperation match = new MatchOperation(Criteria.where("_id").is("1"));
Aggregation aggregate = Aggregation.newAggregation(match, Aggregation.project().and("array").project("size").as("count"));
AggregationResults<CollectionNameClass> aggregateResult = mongoOperations.aggregate(aggregate, "collectionName", <CollectionNameClass>.class);
if (aggregateResult!=null) {
//You can find the "count" as an attrribute inside "result" key
System.out.println("Output ====>" + aggregateResult.getRawResults().get("result"));
System.out.println("Output ====>" + aggregateResult.getRawResults().toMap());
}
Sample output:-
Output ====>[ { "_id" : "3ea8e671-1e64-4cde-bd78-5980049a772b" , "count" : 47}]
Output ====>{serverUsed=127.0.0.1:27017, waitedMS=0, result=[ { "_id" : "3ea8e671-1e64-4cde-bd78-5980049a772b" , "count" : 47}], ok=1.0}
You can write query as
Aggregation aggregate = Aggregation.newAggregation(Aggregation.match(Criteria.where("_id").is(1)),
Aggregation.project().and("array").size().as("count")); mongoTemplate.aggregate(aggregate, collectionName, Integer.class);
It will execute the following query { "aggregate" : "collectionName" , "pipeline" : [ { "$match" : { "_id" : 1}} , { "$project" : { "count" : { "$size" : [ "$array"]}}}]}

Aggregating using Spring mongo group after a project is not finding the correct field

I have a collection with a dataset that looks like:
{
"resource" : "10.10.10.10",
"statistics" : {
"connections" : 17
}
}
{
"resource" : "10.10.10.10",
"statistics" : {
"connections" : 24
}
}
I want to use Mongo's $group/$push mechanism to return a dataset that looks like:
{ "_id" : "10.10.10.10", "statTotals" : [ 17, 24 ] }
In Mongo shell, I can that by doing:
db.testcol.aggregate([ { "$project" : { "resource" : 1 , "total" : "$statistics.connections"}} , { "$group" : { "_id" : "$resource" , "statTotals" : { "$push" : "$total"}}} ])
Now I want to do this using Spring's Mongo data solution in Java. The operations I'm currently trying to use are:
ProjectionOperation projOper = Aggregation.project("resource").and("statistics.connections").as("total");
GroupOperation groupOper = Aggregation.group("resource").push("total").as("statTotals");
Unfortunately, this is generating a pipeline which looks like:
{ "aggregate" : "event" , "pipeline" : [ { "$project" : { "resource" : 1 , "total" : "$statistics.connections"}} , { "$group" : { "_id" : "$resource" , "statTotals" : { "$push" : "$statistics.connections"}}}]}
In the $group, the $push is being done against $statistics.connections instead of $total so the results come back blank.
Any help would be greatly appreciated on this. At first I thought this might be https://jira.spring.io/browse/DATAMONGO-1254 but I've tried using both 1.7.2 as well as 1.8.1 and get the same results.

Java equivalent of scala query in mongodb

What is the equivalent cde in Java:
var result = collectionName.findOne()
println(result.get("name").toString)
To elaborate, This is my sample db:
{ "_id" : ObjectId("4ca039f7a5b75ab98a44b149"), "name" : "kaustubh", "country" : "india" }
{ "_id" : ObjectId("4ca03a85a12344a5e47bcc5c"), "name" : "rahul", "country" : "pakistan" }
{ "_id" : ObjectId("4ca03a9ea12344a5e47bcc5d"), "name" : "swapnil", "country" : "lanka" }
{ "_id" : ObjectId("4ca03b19a12344a5e47bcc5e"), "name" : "sagar", "country" : "nepal" }
i am running the following query on it:
query.put("country", "india");
DBCursor cursor = collection.find(query);
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
that prints:
{ "_id" : { "$oid" : "4ca04b6b37a85ab92557218a"} , "name" : "kaustubh" , "country" : "india"}
as many times as the pair exists in the collection.
how do I formulate a query to get all the names, once and get the count for them.I read the docs, and didnt stumble upon any way to do it.
Try this
query.put("name", "kaustubh");
DBObject myDoc = collection.findOne(query);
System.out.println(myDoc);

Categories