How do I iterate through entries in MongoDB 3.0? - mongodb

We are trying to retrieve entries from the database (MongoDB) and place them in a db. When using DBCursor, we use cursor.hasNext() to get the next reading.
DBCursor is depreciated in MongoDB 2.0 and it is recommended to use FindIterable for MongoDB 3.0.
However when we use FindIterable, there isn't a similar hasNext() method.
How do I change my code below for 3.0?
BasicDBObject query = new BasicDBObject("timeStamp",
new BasicDBObject("$gte",from).append("$lt",to ));
DBCursor cursor = (DBCursor) newColl.find(query);
//FindIterable cursor = newColl.find(query);
while (cursor.hasNext()) {
DBObject latestEntry = cursor.next();
String json = latestEntry.toString();
Reading reading = gson.fromJson(json, Reading.class);
readingList.add(reading);
}
return readingList;

You can try something like below.
Document query = new Document("timeStamp",
new Document("$gte",from).append("$lt",to));
FindIterable<Document> find = newColl.find(query);
for (Document latestEntry : find) {
String json = latestEntry.toJson();
Reading reading = gson.fromJson(json, Reading.class);
readingList.add(reading);
}
return readingList;
Using Cursor
MongoCursor<Document> cursor = newColl.find(query).iterator();
while (cursor.hasNext()) {
Document latestEntry = cursor.next();
String json = latestEntry.toJson();
Reading reading = gson.fromJson(json, Reading.class);
readingList.add(reading);
}
return readingList;
Using Lambda
List<Reading> readingList= newColl.find().map(item -> gson.fromJson(item.toJson(), Reading.class)).into(new ArrayList<>());

Related

Mongo 3.6.3 java driver aggregate hint - returns undefined field 'hint'

I am trying to pass a hint on an aggregate in MongoDB Java Driver 3.6.3. The aggregate API allows for adding a hint as in:
MongoCollection<Document> coll = database.getCollection("myCollection")
ArrayList<BasicDBObject> docList = new ArrayList<BasicDBObject>();
BasicDBObject hint = new BasicDBObject("$hint","reportjob_customerId_1_siiDocumentAttributes.deleted_1");
MongoCursor<Document> cursor = coll.aggregate(docList).hint(hint).allowDiskUse(batchContext.isAllowDiskUse()).iterator();
I've tried with $hint and hint, but Mongo always returns Command failed with error -1: 'unrecognized field 'hint'
How do I properly send the hint on the aggregate call?
Looks like there is no support to pass the index name directly to hint. So you have pass the index creation document to the hint which you can get by name and use key to get the index document.
MongoCollection<Document> coll = database.getCollection("myCollection");
Bson index = coll.listIndexes().into(new ArrayList<>()).stream().filter(item -> item.getString("name").equals("reportjob_customerId_1_siiDocumentAttributes.deleted_1")).findFirst().get().getString("key");
List<BasicDBObject> docList = new ArrayList<BasicDBObject>();
MongoCursor<Document> cursor = coll.aggregate(docList).hint(index).allowDiskUse(batchContext.isAllowDiskUse()).iterator();
Legacy driver had support for both index name and document.
MongoClient client = new MongoClient();
DB database = client.getDB("myDatabase");
DBCollection coll = database.getCollection("myCollection");
List<BasicDBObject> docList = new ArrayList<BasicDBObject>();
AggregationOptions options = AggregationOptions.builder().allowDiskUse(batchContext.isAllowDiskUse()).build();
DBCursor dbCursor = ((DBCursor) coll.aggregate(docList, options)).hint("reportjob_customerId_1_siiDocumentAttributes.deleted_1");
You can create a jira to have the option to pass index name in the new driver here

MongoDB : How to find multiple documents and update at the same time?

I have mongo DB and I am using C#.Net to interact with mongo db. C# API has methods for finding a single document and updating it at the same time. For example FindOneAndUpdateAsync.
However I couldn't find any method to find multiple documents and update them at the same time asynchronously.
The code below finding and processing each document asynchronously. How do I also update that document at the same time?
public async Task<IList<IDictionary<string, string>>> DoWork()
{
var collection = _mongoDatabase.GetCollection<BsonDocument>("units");
var filterBuilder = Builders<BsonDocument>.Filter;
var filter = filterBuilder.Ne<string>("status", "INIT") &
(filterBuilder.Exists("isDone", false) |
filterBuilder.Eq<bool>("isDone", false));
// I want to pass this update filter to update the document. But not sure how
var update = Builders<BsonDocument>.Update
.CurrentDate("startTime");
var sort = Builders<BsonDocument>.Sort.Ascending("startTime");
var projection = Builders<BsonDocument>.Projection
.Include("_id")
.Include("fileName"); // for bravity i have removed other projection elements
var output = new List<IDictionary<string, string>>();
// How do i pass update filter and update the document at the same time??
await collection
.Find(filter)
.Sort(sort)
.Project(projection)
.ForEachAsync((unit) =>
{
var dictionary = new Dictionary<string, string>();
Recurse(unit, dictionary);
output.Add(dictionary);
});
return output.Count > 0 ? output : null;
}
That doesn't exist in the mongo .Net api see here.
Just use a combination of Find and UpdateManyAsync.

MongoDB Taking Too Long time in C#.net

I am retrieving data from mongoDB using C# driver, It is taking a lot of time when i do to list Please help me
My Mongoquery is
var documentReportIds = new BsonValue[] { LatestReportIds };
var documentChennelIds = new BsonValue[] { Cid };
var documentPropertyIds = new BsonValue[] { Pid };
IMongoQuery query = new QueryDocument();
query = Query.And(Query.GTE("CheckInDate", startdate.Date.AddMinutes(330)),
Query.LTE("CheckInDate", endDate.Date.AddMinutes(330)));
query = Query.And(query, Query.EQ("SubscriberPropertyId", reportFilter.SubscriberPropertyId));
query = Query.And(query, Query.EQ("LengthOfStay", reportFilter.LOS));
query = Query.And(query, Query.In("ReportId", documentReportIds));
query = Query.And(query, Query.In("ChannelId", documentChennelIds));
query = Query.And(query, Query.In("PropertyId", documentPropertyIds));
MongoDBEntities<ScheduleOptimizationReportDetails> _obj = new MongoDBEntities<ScheduleOptimizationReportDetails>();
var list= _obj.GetSchedularOptimizationJoin(query);
Class from where it perform data retrieving
public class MongoDBEntities<T>
{
MongoDatabase db = MongoDBInstance.GetMongoDatabase;
public List GetSchedularOptimizationJoin(IMongoQuery query)
{
MongoCollection MCollection = db.GetCollection(“Subscription_OptimisedReports”);
MongoCursor cursor = MCollection.FindAs(query).SetFields(Fields.Include(“ScheduleLogId”, “SubscriberPropertyId”, “CheckInDate”, “ReportId”, “CreatedDate”));
List entities = cursor.ToList();
return entities ;
}
}
what is another option to select data in C#, I have also applied indexing on column.
Please help me how to solve it.
You can use the MongoDB.Driver.Linq package to help you create your querys with Linq expressions.

Query without condition in MongoDB + C#

I'm trying to use the collection.FindAndModify and give it a IMongoQuery which selects all the documents. But I can not find how to create a query without any conditions!
Can anyone tell me how to do this? I'm using MongoDB C# Driver v1.8.3.
Here's my code:
var query = ???;
var sortBy = SortBy.Ascending(new string[] { "last_update" });
var update = Update<Entity>.Set(e => e.last_update, DateTime.Now);
var fields = Fields.Include(new string[] { "counter", "_id" });
var m = collection.FindAndModify(query, sortBy, update, fields, false, false);
I wonder what should I write in place of ??? to select all the documents!?
Use an empty QueryDocument:
var query = new QueryDocument();
But keep in mind that FindAndModify will only modify the first matching document.

using findAndModify in mongodb using grails gorm

I need to use findAndModify in my application with grails and mongoDB.
I used this code :
public static String getNextId(DB db, String seq_name) {
String sequence_collection = "seq"; // the name of the sequence collection
String sequence_field = "seq"; // the name of the field which holds the sequence
DBCollection seq = db.getCollection(sequence_collection); // get the collection (this will create it if needed)
// this object represents your "query", its analogous to a WHERE clause in SQL
DBObject query = new BasicDBObject();
query.put("_id", seq_name); // where _id = the input sequence name
// this object represents the "update" or the SET blah=blah in SQL
DBObject change = new BasicDBObject(sequence_field, 1);
DBObject update = new BasicDBObject("$inc", change); // the $inc here is a mongodb command for increment
// Atomically updates the sequence field and returns the value for you
DBObject res = seq.findAndModify(query, new BasicDBObject(), new BasicDBObject(), false, update, true, true);
return res.get(sequence_field).toString();
}
and it work successful. But now I want use findAndModify without native mongodb object, and with using GORM.
Is there any solution for this work?
There is not way to accomplish this without native API, you can however write your code a bit more compact like this:
def collection = Seq.collection
collection.findAndModify([_id: seq_name ], [ "\$inc": [seq:1] ])
Config your DataSource.groovy with db configurations.
Then define a Domain class:
Class Seq{
int seq
}
And use dynamic finder in a sevice:
Class SeqService {
String findAndModify(String seq_name) {
def seqInstance = Seq.get(seq_name)
if(seqInstance){
seqInstance.seq ++
seqInstance.save()
return seqInstance.seq.toString()
}
return '' //instance not found
}
}
Then make a call when you need that action:
def seqService
def id
.......
def result = seqService.findAndModify(id)
....