Bulk delete using Ravendb - c#

I am trying to delete documents ids from a collection in RavenDB using the below logic
var documentstore = new DocumentStore
{
Url = "http://localhost:8080",
DefaultDatabase = "Employee"
};
documentstore.Initialize();
using (var session = documentstore.OpenSession())
{
var test = new List<string>();
test.Add("emps/81993");
test.Add("emps/40319");
var w1 = session.Load<Employee>(test);
session.Delete(w1);
session.SaveChanges();
}
I get the below error
Models.Employee[] is not associated with the session, cannot delete unknown
How do I go about doing a bulk delete of document Ids from the collection?
Thanks

You are trying to delete the array of employees, not each employee itself. When you pass in an Enumerable in the Load, you will get an array back containing each entity.
Try this instead:
using (var session = documentstore.OpenSession())
{
var test = new List<string>();
test.Add("emps/81993");
test.Add("emps/40319");
Employee[] employees = session.Load<Employee>(test);
foreach (var employee in employees)
{
session.Delete(employee);
}
session.SaveChanges();
}
To further explain, the returned array is not tracked by RavenDb's UoW, but each individual item in the array is, that's why you get the message about Employee[] is not associated with the session.

You can use set based operation.
The following code will query specific index and delete everything matching the query
var operation = store.DatabaseCommands.DeleteByIndex("Index Name", new IndexQuery
{
Query = "Lucene query of stuff to delete"
}, options: null);
for example, the following code will delete all documents from a document collection called "Companies" (excerpt from one of RavenDB unit tests)
var operation = documentStore.DatabaseCommands.DeleteByIndex("Raven/DocumentsByEntityName", new IndexQuery
{
Query = "Tag:[[Companies]]"
});
You can read more in this link to RavenDB documentation

Related

C# MongoDB Update / Upsert List<Object> to Collection

I was searching for a way to Update / Upsert in MongoDB a List of items to a MongoDB collection.
Is there any way to do it or I have to use a loop to update the items one by one?
P.S: The problem is not making a method that would do the Job (one by one) but I want to avoid too much iterations with the MongoDB database.
Here's the method that I'm currently using:
public static void UpdateAll()
{
var client = new MongoClient("mongodb://server_ip:27017");
var db = client.GetDatabase("M_PROJECT");
var collection = db.GetCollection<Product>("products");
//Config.Products is a List<Product> that was previously retrieved from the same collection in MongoDB
foreach(Product product in Config.Products)
{
var filter = Builders<Product>.Filter.Eq(p => p.ID, product.ID);
var update = Builders<Product>.Update.Set("Name", product.Name).Set("Price", 20);
collection.UpdateOne(filter, update, new UpdateOptions() { IsUpsert = true });
}
}
And maybe without specifying every Field/Property that I want to update, but just applying the class instance.
try a bulk replace like so:
var models = new List<WriteModel<Product>>();
foreach (var product in Config.Products)
{
if (product.ID == null) product.ID = ObjectId.GenerateNewId();
var upsert = new ReplaceOneModel<Product>(
filter: Builders<Product>.Filter.Eq(p => p.ID, product.ID),
replacement: product)
{ IsUpsert = true };
models.Add(upsert);
}
collection.BulkWrite(models);
the thing to note here is that it will completely overwrite the data stored in the db with the data from your product class instances. but i think you'd be okay cause you said the products are retrieved from the same collection.
this is what my library MongoDB.Entities does internally to achieve products.Save()
Yes, you can use UpdateMany() instead of UpdateOne(). See https://www.mongodb.com/blog/post/quick-start-csharp-and-mongodb--update-operation and https://mongodb.github.io/mongo-csharp-driver/2.9/apidocs/html/M_MongoDB_Driver_IMongoCollectionExtensions_UpdateMany__1.htm for more details.

How to get the list of objects that have just been inserted into the table in the entity framework

The best way to get object list has just been inserted into the
database?
I have the code to add a new object list to the database, I want to retrieve the list of objects without having to select again from the database.
I expect something like insert in the SQL Server trigger.
Here is my code snippet.
List<string> productNames = new List<string>();
foreach (var name in productNames)
{
var product = new Product {Name = name, Color = "something", Body="something body" };
DbContext.Products.Add(product);
}
DbContext.SaveChanges();
var result = ListProductsInserted; // I want to get list product
I do not want to rewrite the query to retrieve data from the database
again.
Is there a better way?
If I understaood your question properly, Use code below
List<string> productNames = new List<string>();
List<Product> holdProducts = new List<Product>();
foreach (var name in productNames)
{
var product = new Product {Name = name, Color = "something", Body="something body" };
DbContext.Products.Add(product);
holdProducts.Add(product);
}
DbContext.SaveChanges();
var result = holdProducts;
The easiest way for you would be DbEntityEntry.Reload()
you can use it like this:
yourContext.Entry(yourEntity).Reload();

couchbase server not return manually added document(which i added in create bucket option on couchbase server) in bucket using c# code

when we get documents from couchbase server using select query not documents which i added manually only programatically added record return(using cluster in c# i added in couchbase server) but i want all the documents
my code below . what i am missing
var clientConfiguration = new ClientConfiguration();
clientConfiguration.Servers = new List<Uri> { new Uri("http://localhost:8091/pools/") };
List<string> objDocList = new List<string>();
Cluster Cluster = new Cluster(clientConfiguration);
var bucket = Cluster.OpenBucket();
var result = bucket.Query<dynamic>("select * from testbucket");
foreach (var row in result)
{
dynamic propJSON = JsonConvert.SerializeObject(row);
//propJSON not contain id
}
As written your query is hitting the default bucket, not the testbucket. You should also wrap your bucket in a using statement.
You'll likely need to create a primary index on your testbucket. This answer gives the best discussion of what's necessary.
Your code will end up being something like...
using (var bucket = Cluster.OpenBucket("TestCheck2"))
{
var query = bucket.CreateQuery("dev_testcheck2", "getall");
var data = bucket.Query<dynamic>(query);
foreach (var item in data.Rows)
{
Console.WriteLine($"{item.Value[0]}: Title: \"{item.Value[1]}\" Body: {item.Value[2]}");
}
}
dev_testcheck2 is the suffix of the name of my development view design document and getall is the name of my view.

Insert collection into List from MongoDB

I try to get all data from collection into MongoDB server using C# driver.
The idea is connect to the server and get all collection than insert into list of class.
List<WatchTblCls> wts;
List<UserCls> users;
List<SymboleCls> syms;
public WatchTbl()
{
InitializeComponent();
wts = new List<WatchTblCls>();
users = new List<UserCls>();
syms = new List<SymboleCls>();
}
public async void getAllData()
{
client = new MongoClient("mongodb://servername:27017");
database = client.GetDatabase("WatchTblDB");
collectionWatchtbl = database.GetCollection<WatchTbl>("Watchtbl");
collectionUser = database.GetCollection<UserCls>("Users");
collectionSymbole = database.GetCollection<SymboleCls>("Users");
var filter = new BsonDocument();
using (var cursor = await collectionWatchtbl.FindAsync(filter))
{
while (await cursor.MoveNextAsync())
{
var batch = cursor.Current;
foreach (var document in batch)
{
wts.Add(new WatchTblCls(document["_id"], document["userId"], document["wid"], document["name"], document["Symboles"]));
}
}
}
}
I get this error under
wts.Add(new WatchTblCls(document["_id"], document["userId"], document["wid"], document["name"], document["Symboles"]));
Cannot apply indexing with [] to an expression of type 'WatchTbl'
I don't understand the reason behind using WatchTbl and WatchTblCls both together. Is WatchTblCls a model for the entity WatchTbl here? Im not sure.
In any case. If you go for aggregation and want to convert WatchTbl collection to WatchTblCls list, your desired solution might look like the following. I don't know the defiitions of the classes so I'm assuming:
var client = new MongoClient("mongodb://servername:27017");
var database = client.GetDatabase("WatchTblDB");
var collectionWatchtbl = database.GetCollection<WatchTbl>("Watchtbl");
var collectionUser = database.GetCollection<UserCls>("Users");
var collectionSymbole = database.GetCollection<SymboleCls>("Users");
var list = collectionWatchtbl.AsQueryable().Select(x => new WatchTblCls() {
id = x.id,
userId = x.userId,
.....
});
If you can use the same WatchTbl class and still want to load the full collection to a local List (which is definitely not a good idea):
List<WatchTbl> list = await collectionWatchtbl.Find(x => true).ToListAsync();

How to delete several documents by ID in one operation using Elasticsearch Nest

I am building some abstraction functions for my application to call, which will hit elasticsearch through Nest. One of such functions is a Delete(string id) call, which is easy to accomplish. I have done this as follows:
public void Delete(string id)
{
esClient.Delete(id);
}
Now let's say I want to do the same thing, but operate on several documents simultaneously. My original hunch was to do something like this:
public void Delete(IEnumerable<string> ids)
{
esClient.DeleteMany(ids); // won't compile
}
As my comment states, doing this won't compile. What is the proper way of batch deleting documents by ID in Nest?
To use esClient.DeleteMany(..) you have to pass collection of objects to delete.
var objectsToDelete = new List<YourType> {.. };
var bulkResponse = client.DeleteMany<YourType>(objectsToDelete);
You can get around this by using following code:
var ids = new List<string> {"1", "2", "3"};
var bulkResponse = client.DeleteMany<YourType>(ids.Select(x => new YourType { Id = x }));
Third option, use bulk delete:
var bulkResponse = client.Bulk(new BulkRequest
{
Operations = ids.Select(x => new BulkDeleteOperation<YourType>(x)).Cast<IBulkOperation>().ToList()
});
I was working on a .NET client for ElasticSearch 5.x, and I was fortunate to have the following code running (as well as succeeding all unit tests) for bulk deletion using ID's:
//IList<string> ids = ...
var descriptor = new BulkDescriptor();
foreach (var id in ids.Where(x => !string.IsNullOrWhiteSpace(x)))
descriptor.Delete<T>(x => x
.Id(id))
.Refresh(Refresh.WaitFor);
var response = await _client.BulkAsync(descriptor);

Categories

Resources