get some attributes from mongodb except one or two - java

I would like to get some information which is in a mongoDB except some attributes.
I tried it in cmd and it worked:
db.orders.find({name:"chabeee"},{_id:0, name:1, worksAt:1})
Then I get this result:
{ "name" : "chabeee", "worksAt" : "jobAtBp" }
{ "name" : "chabeee", "worksAt" : "jobAtRE" }
Its okay, but I want to get in a Java Program. How can I do that?

You have to create one additional BasicDBObject, which will be used for pointing out which exact keys to be fetched. And finally the DBCollection#find(DBObject ref, DBObject keys) method has to be invoked in order to pass the desired projection keys.
BasicDBObject query = new BasicDBObject("name", "chabeee");
BasicDBObject keys = new BasicDBObject();
keys.put("_id", 0);
keys.put("name", 1);
keys.put("worksAt", 1);
BasicDBCursor result = collection.find(query, keys);
Then you just have to iterate over the BasicDBCursor and verify the result.
while (cursor.hasNext()) {
System.out.println(cursor.next());
}

Related

Why the aggregate function does not give the desired result?

Was trying to change the data type of all values in a specific field, without use of iterators.
Here tid is the field name
I tried running the code in Mongo using
var ch ={"$addFields" : { "tid" : { "$convert":{"input":"$tid" , "to" : 2}}}}
db.test.aggregate(ch);
Where test is my collection
Java Code :
BasicDBObject fieldObject = new BasicDBObject();
fieldObject.put("$convert",new BasicDBObject().append("input",
"$tid").append("to", 2));
BasicDBObject addField = new BasicDBObject("$addFields",new
BasicDBObject("tid",fieldObject));
System.out.println(addField);
List<BasicDBObject> options = new ArrayList<>();
options.add(addField);
details.aggregate(options);
When I ran the code in mongo command line, the data types are changing from Integer to String.
But no change when I run the same through java code. Is there any issue with my Java Code.

Save Mongodb aggregation results on multiple id field in a new collection

I have to aggregate some data in mongodb through the java driver, and save the aggregation result in a new collection, and later print this collection in a Jtable; the id field can be not simple in my case (i can't know if it is a single value or not) so I followed this:
How to write multiple group by id fields in Mongodb java driver
when I want to save the result in a new collection, doing this:
for (DBObject result : output.results()) {
report.insert(result);
}
i have this error:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: fields stored in the db can't have . in them. (Bad Key: 'store.address.store_state')
this is a piece of the collection where I do the aggregation:
{
"_id" : ObjectId("549ef5d17c8db9efa75d49c9"),
"store" : {
"store_id" : NumberLong(2),
"store_type" : "Small Grocery",
"region_id" : NumberLong(78),
"store_name" : "Store 2",
"store_number" : NumberLong(2),
"address" : {
"store_street_address" : "5203 Catanzaro Way",
"store_city" : "Bellingham",
"store_state" : "WA",
"store_postal_code" : "55555",
"store_country" : "USA",
"store_manager" : "Smith"
},
.....}
Can anyone help me?
Note: ID Field can be simple (only a field) or complex (two or more fields)
The new collection I want to create must have all the fields that compose the ID in the aggregation, and all the fields result by aggregation. That's beacause I had to print that collection in this way: Retrieve data from MongoDB collection into Swing JTable
for example:
DBObject fields = new BasicDBObject("unit_sales", 1);
fields.put("store.store_type", 1);
fields.put("store.store_name", 1);
fields.put("store.address.store_city", 1);
fields.put("_id", 0);
DBObject project = new BasicDBObject("$project", fields );
Map<String, Object> dbObjIdMap = new HashMap<String, Object>();
dbObjIdMap.put("store_type", "$store.store_type");
dbObjIdMap.put("store_name", "$store.store_name");
dbObjIdMap.put("store_city", "$store.address.store_city");
DBObject groupFields = new BasicDBObject( "_id", dbObjIdMap);
groupFields.put("average", new BasicDBObject("$avg", "$unit_sales"));
DBObject group = new BasicDBObject("$group", groupFields);
AggregationOutput output = collection.aggregate(project, group);
So i want as result a table with column store_type,store_name, store_city, average.
I know I'm exposing my problem here so bad, but i'm not english and i don't speak very well the language, so please try to understand me.. sorry

MongoDB-Java: How to make $geoNear to first do query, then distance?

I'm trying to query and sort documents as followed:
Query only for documents older than SOMETIME.
Within range of AROUNDME_RANGE_RADIUS_IN_RADIANS.
Get distance for each document.
Sort them by time. New to Old.
Overall it should return up to 20 results.
But it seems that since $geoNear is by default limited to 100 results, I get unexpected results.
I see $geoNear working in the following order:
Gets docs from the entire collection, by distance.
And only then executes the given Query.
Is there a way to reverse the order?
MongoDB v2.6.5
Java Driver v2.10.1
Thank you.
Example document in my collection:
{
"timestamp" : ISODate("2014-12-27T06:52:17.949Z"),
"text" : "hello",
"loc" : [
34.76701564815013,
32.05852053407342
]
}
I'm using aggregate since from what I understood it's the only way to sort by "timestamp" and get the distance.
BasicDBObject query = new BasicDBObject("timestamp", new BasicDBObject("$lt", SOMETIME));
// aggregate: geoNear
double[] currentLoc = new double[] {
Double.parseDouble(myLon),
Double.parseDouble(myLat)
};
DBObject geoNearFields = new BasicDBObject();
geoNearFields.put("near", currentLoc);
geoNearFields.put("distanceField", "dis");
geoNearFields.put("maxDistance", AROUNDME_RANGE_RADIUS_IN_RADIANS));
geoNearFields.put("query", query);
//geoNearFields.put("num", 5000); // FIXME: a temp solution I would really like to avoid
DBObject geoNear = new BasicDBObject("$geoNear", geoNearFields);
// aggregate: sort by timestamp
DBObject sortFields = new BasicDBObject("timestamp", -1);
DBObject sort = new BasicDBObject("$sort", sortFields);
// aggregate: limit
DBObject limit = new BasicDBObject("$limit", 20);
AggregationOutput output = col.aggregate(geoNear, sort, limit);
You could add a $match stage at the top of the pipleine, to filter the documents before the $geonear stage.
BasicDBObject match = new BasicDBObject("timestamp",
new BasicDBObject("$lt", SOMETIME));
AggregationOutput output = col.aggregate(match,geoNear, sort, limit);
The below piece of code now, is not required,
geoNearFields.put("query", query);

Add new data to existing collection in mongo in java

I need two to add new items to the existing data in mongo db.
This is mongo db I have the following data.
{
"_id" : ObjectId("53ce11e7d0881d32d9fa935f"),
"name" : "massive riots",
"lastFeachedTime" : "Jul 15, 2014 12:55:27 PM"
}
Here I have to find the data based on name and the I have to add another two items two it.
Here is my code.
DBObject queryObject = new BasicDBObject().append("name", keyword);
if (null == newFetchTime) {
}
DBObject updateObject = new BasicDBObject();
updateObject.put("nextPageToken", nextPageToken);
updateObject.put("prevPageToken", prevPageToken);
Utils utils = new Utils();
DBCollection collection = utils.getStaging().getCollection("test");
collection.update(queryObject, updateObject, true, false);
But I am do update the existing value get removed and the new data get added.
Can any one tell me how to add the items to the existing data in mongo db.
You want the $set operator in your update. This allows the specified fields to be altered without affecting any of the existing fields in the document, unless the specified field exists in which case that field is overwritten:
DBObject update = new BasicDBObject(
"$set", new BasicDBObject()
.append("nextPageToken",nextPageToken)
.append("prevPageToken",prevPageToken)
);
Works out to the equivalent in shell:
{ "$set" : { "nextPageToken" : nextPageToken , "prevPageToken" : prevPageToken }}

MongoDB and Java: What's wrong with my update?

I'm using MongoDB with the Java driver and have a Collection 'Questions' with the following format for each entry:
{
"question" : "How are you?",
"category" : "personal",
"isTrain" : true,
"processed" : true
}
What I want to do is take every entry with both "processed" and "isTrain" equal to true, and I want to set their "processed" value to false. The code in which I'm trying to use for this is:
public void markUnprocessed(boolean isTrain) {
BasicDBObject queryObj = new BasicDBObject();
queryObj.put("processed", true);
queryObj.put("isTrain", isTrain);
BasicDBObject updateObj = new BasicDBObject();
updateObj.put("processed", false);
collection.updateMulti(queryObj, updateObj);
}
Calling this function from my code seems to have no effect, and I'm not sure why. Any help on the matter would be greatly appreciated.
Thanks,
Chris Covert
You need to do a partial using $set, not a full update.
With current statement you would be losing all the other fields.
BasicDBObject updateObj = new BasicDBObject();
updateObj.put("$set", new BasicDBObject("processed", false));
Also note that you should turn on safe writes (using WriteConcern.SAFE) so that your app gets notified of any error from server.

Categories