How to query List<BsonDocument>batch Mongo database using Field values/contents - mongodb

The codes below can be used to query mongo data imported from a DataTable and output viewed via a MessageBox.I have verified that it works after some difficulties of matching uppercase and lowercase of terms to be queried
MongoClient mongo = new MongoClient("mongodb://localhost");
MongoServer server;
MongoDatabase database;
private void Form1_Load(object sender, EventArgs e)
{
server = mongo.GetServer();
server.Connect();
database = server.GetDatabase("test");
List<BsonDocument> batch = new List<BsonDocument>();
foreach (DataRow dr in dt.Rows)
{
var dictionary = dr.Table.Columns.Cast<DataColumn> ().ToDictionary(col => col.ColumnName, col => dr[col.ColumnName]);
batch.Add(new BsonDocument(dictionary));
}
MongoCollection<MongoDB.Bson.BsonDocument> collec = database.GetCollection<BsonDocument>("test");
collec.InsertBatch(batch); //// produces BsonIds for enteries
var results = batch.ToList();
string json = results.ToJson();
MessageBox.Show(json);
////Part I am struggling with
var query = new QueryDocument("Column1", "Henry");// PAY ATTENTION TO UPPER/LOWERCASE OF WORDS TO BE QUERIED
collec.Find(query).ToList(); // THIS PICKS CORRESPONDING RECORDS FROM THE MONGODB
}

The above codes worked after reconciling uppercase/lowercase of letters in the query items

Related

Using GET to return data in MongoDB

I am trying to connect to MongoDB with Web Api, trying to return the connected data in MongoDB using Get. The name of the database is "test" and the collection name is "restaurant".
Here is the code I have
public IEnumerable<restaurants> Get()
{
var client = new MongoClient();
var dbs = client.GetDatabase("test");
var collection = dbs.GetCollection<restaurants>("restaurants");
return collection;
}
The last collection word is underlined, and I have not found what needs to be returned (in place of collection) in order to show the database in MongoDB (using postman).
I think you are trying to return IMongoCollection, not IEnumerable so last line is underlined :)
Try to transform collection to List (asynchronously), then return. For example:
public Task<List<restaurants>> GetRestaurantsAsync()
{
var client = new MongoClient();
var dbs = client.GetDatabase("test");
var collection = dbs.GetCollection<restaurants>("restaurants");
return await collection.Find(_ => true).ToListAsync();
}
public async Task MainAsync()
{
List<restaurants> restaurantsList = await GetRestaurantsAsync();
}
Note: it depends on which version of mongo c# driver you're using.

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.

Copying a mongo collection using Java Driver

I want to copy the contents from one collection to another.
in mongod this can be done:
db.tempMongoItem.find().forEach( function(x){db.mongoItem.insert(x)} )
Using Java Mongo Driver, I try:
DB db = mongoClient.getDB("mydb")
CommandResult result = db.command("db.tempMongoItem.find().forEach( function(x){db.mongoItem.insert(x)} )")
But I get:
result = [serverUsed:localhost:27017, ok:0.0, errmsg:no such cmd: db.tempMongoItem.find().forEach( function(x){db.mongoItem.insert(x)} ), code:59, bad cmd:[db.tempMongoItem.find().forEach( function(x){db.mongoItem.insert(x)} ):true]]
Any ideas?
You need to emulate the same thing JS is doing in Java, which means getting a cursor and iterating over it, inserting each document into new collection.
Something like this (coll is current, coll2 is new collection):
DBCursor cursor = coll.find();
try {
while(cursor.hasNext()) {
coll2.insert(cursor.next());
}
} finally {
cursor.close();
}
Both coll and coll2 are assumed to be DBCollection type.
Since it appears you are copying within the same DB, there is another way to do this if you are using 2.6 MongoDB using aggregation framework $out stage:
db.collection.aggregate({"$out":"newCollection"});
Note that this is limited to outputting into the same DB that original collection is in.
The following JAVA code will copy the collection from source to destination for a given database name (using mongodb-driver 3.0.4)
/** Clone a collection.
*
* #param fromCollectionName - The name of collection to be cloned
* #param toCollectionName - The name of the cloned collection
* #param dbName - The name of the database
*/
public void cloneCollection(String fromCollectionName, String toCollectionName, String dbName) throws MongoException {
MongoCollection toCol = this.getCollection(toCollectionName, dbName);
if (toCol != null) {
throw new MongoException("The destination collection already exists.");
}
List<Document> ops = new ArrayList<>();
ops.add(new Document("$out",toCollectionName));
MongoCollection sourceCollection = this.getCollection(fromCollectionName, dbName);
sourceCollection.aggregate(ops);
}
public MongoCollection getCollection(String collection, String dbName) {
MongoClient mongo = new MongoClient(new ServerAddress("localhost", Integer.parseInt(port)));
MongoDatabase database = mongo.getDatabase(dbName);
return curdb.getCollection(collection);
}
Please note that this will not copy over the indices that you have created in source collection. You will have to copy the indices seperately
Following up on Asya's response, you can use Java 8 Lambda functions to do:
collSource.find().forEach((Block<Document>) collTarget::insertOne);

how rebuild lucene indexes over hibernate search jpa with mongodb

I have accidentally deleted my index directory, now i am trying to rebuild all indexes.
I am using the hibernate search with JPA, lucene and MONGODB.
the following method is returning no results
public void rebuildIndex()throws Exception{
org.hibernate.search.jpa.FullTextEntityManager fem = org.hibernate.search.jpa.Search.getFullTextEntityManager(entityManager);
org.hibernate.search.query.dsl.QueryBuilder queryBuilder = fem.getSearchFactory().buildQueryBuilder().forEntity(Person.class).get();
org.apache.lucene.search.Query query = queryBuilder.all().createQuery();
FullTextQuery fullTextQuery = fem.createFullTextQuery(query, Person.class);
//fullTextQuery.initializeObjectsWith(ObjectLookupMethod.SKIP, DatabaseRetrievalMethod.FIND_BY_ID);
System.out.println(fullTextQuery.toString());
List<Person> results = fullTextQuery.getResultList();
fem.clear();
System.out.println(results.size());
for(Person p : results){
fem.index( p );
fem.flushToIndexes();
fem.clear();
}
//fem.createIndexer().startAndWait();
}
the method is returning no result. how should I get all data from mongoDb to rebuild index?
as hibernate search didn't work with criteria neither with JPQL and has his own JP-QL parser.
I couldn't create a findAll method to retrieve all objetcs
the only way was use a native mongoDb query:
org.hibernate.search.jpa.FullTextEntityManager fem = org.hibernate.search.jpa.Search.getFullTextEntityManager(entityManager);
Mongo mongo = new Mongo("127.0.0.1", 27017);
DB db = mongo.getDB("mainBase");
DBCollection dbCollection = db.getCollection("Persons");
DBCursor cursor = dbCollection.find();
Collection<String> ids = new ArrayList<String>();
String id = "";
while (cursor.hasNext()) {
id = cursor.next().get("_id").toString();
System.out.println(id);
ids.add(id);
}
System.out.println(">"+ids.size());
Person pes;
for(String p : ids){
pes = new Person();
pes.setId(p);
pes = find(pes);
System.out.println("indexing: "+pes.getId());
fem.index( pes );//index each element
fem.flushToIndexes();//apply changes to indexes
fem.clear();//free memory since the queue is processed
}

Performance question about Mongo database

today I have tested the Mongo database, but I got a performance issue.
After I insert 1.800.00, I tried to make a sum of all values but it too 57s.
Then I tried the same thing in MSSQL and took 0s!!
Can you give any tips what I'm doing wrong?
Is this a Mango limitation?
static void Main(string[] args)
{
//Create a default mongo object. This handles our connections to the database.
//By default, this will connect to localhost, port 27017 which we already have running from earlier.
var connStr = new MongoConnectionStringBuilder();
connStr.ConnectTimeout = new TimeSpan(1, 0, 0);
connStr.SocketTimeout = new TimeSpan(1, 0, 0);
connStr.Server = new MongoServerAddress("localhost");
var mongo = MongoServer.Create(connStr);
//Get the blog database. If it doesn't exist, that's ok because MongoDB will create it
//for us when we first use it. Awesome!!!
var db = mongo.GetDatabase("blog");
var sw = new Stopwatch();
sw.Start();
//Get the Post collection. By default, we'll use the name of the class as the collection name. Again,
//if it doesn't exist, MongoDB will create it when we first use it.
var collection = db.GetCollection<Post>("Post");
Console.WriteLine(collection.Count());
sw.Stop();
Console.WriteLine("Time: " + sw.Elapsed.TotalSeconds);
sw.Reset();
sw.Start();
var starting = collection.Count();
var batch = new List<Post>();
for (int i = starting; i < starting + 200000; i++)
{
var post = new Post
{
Body = i.ToString(),
Title = "title " + i.ToString(),
CharCount = i.ToString().Length,
CreatedBy = "user",
ModifiedBy = "user",
ModifiedOn = DateTime.Now,
CreatedOn = DateTime.Now
};
//collection.Insert<Post>(post);
batch.Add(post);
}
collection.InsertBatch(batch);
Console.WriteLine(collection.Count());
sw.Stop();
Console.WriteLine("Time to insert 100.000 records: " + sw.Elapsed.TotalSeconds);
//var q = collection.Find(Query.LT("Body", "30000")).ToList();
//Console.WriteLine(q.Count());
sw.Reset();
sw.Start();
var q2 = collection.AsQueryable<Post>();
var sum = q2.Sum(p => p.CharCount);
Console.WriteLine(sum);
sw.Stop();
Console.WriteLine("Time to sum '" + q2.Count() + "' Post records: " + sw.Elapsed.TotalSeconds); //PROBLEM: take 57 to SUM 1.000.000 records
}
}
Performance issue in the following row:
var q2 = collection.AsQueryable<Post>();
In row above you loading all posts from the posts collection into memory, because of driver does not support linq. In MSSQL it's taking less than second because of linq and calculating will go through the database. Here i guess almost all 57 second need to load data into memory.
In mongodb to achieve best performance you need to create extra fields (de normalize data) and calculate any sums,counters, etc whenever it possible. If it not possible you need to use map/reduce or available aggregate functions, like group (good fit for your example of sum calculation).