Querying RavenDB - c#

I am able to insert and delete data in a RavenDB store. I am also able to run queries that return multiple documents.
I am however unable to load data using session.Load<Book>("books/0") which returns null. Additionally, I get an InvalidOperationException when I try and run a query that searches for a book with a given ID but this particular behavior is expected.
Is there anything I am missing when fetching the doc?
Code Block:
using (var session = DocumentStoreHolder.Store.OpenSession())
{
for (int i = 0; i < count; i++)
{
var doc = session.Load<Book>(i);
Console.WriteLine(doc);
}
}

Do you have a document with the id books/0?
Typically document ids start with 1, so you'll have books/1, etc.

It's been a little while since I used Raven but I believe you need to use a Query not Load.
using (var session = DocumentStoreHolder.Store.OpenSession())
{
var books = session.Query<Book>().ToList();
books.ForEach(book =>
{
//Note that book is an object, write out one of it's properties
Console.WriteLine(book.Name);
});
//or get single book:
var id = 1;
var book = session.Query<Book>()
.FirstOrDefault(x => x.ID == id);
}

Related

Xamarin.iOS/How to retrieve a record from CloudKit by using only the Key

I was reading the Xamarin iOS documentation about CloudKit but it seems is not clear enough how to get the values of a specific record.
In the code below is what the documentation says how to fetch a record by using the "RecordID" but the recordID is generated on the cloudKit so I can't know the ID.
`
// Create a record ID and fetch the record from the database
var recordID = new CKRecordID("MyRecordName");
ThisApp.PublicDatabase.FetchRecord(recordID, (record, err) => {
// Was there an error?
if (err != null) {
...
}
});
`
I tried to use a Query to fetch a record by using the "Key" and the "Value" as the documentation suggest like this
NSPredicate.FromFormat(string.Format("{0} = '{1}'", key, value)), which it works only because I know both the Key and Value, but in the production mode all I know is the "Key", the "Value" it will be generated and saved on the icloud.
An alternative solution that I can think is to retrieve all records for a specific reference type and from there find the one that I want by using the "Key" but I'm not sure what "NSPredicate" command should I use to retrieve all.
So I finaly figured it out how to solve the issue.
My alternative thought was to retrieve all records for a specific reference type, which I achieved that by using the following "NSPredicate"
var predicate = NSPredicate.FromValue(true);
var query = new CKQuery(recordType, predicate);
var result = await PublicDatabase.PerformQueryAsync(query, CKRecordZone.DefaultRecordZone().ZoneId);
This will return a CKRecord[] array including all of my saved records.
Finaly I loop throught the array and use my "Key" to check which record has a value like this
string ret = "";
for(nint i = 0; i < result.Length; ++i)
{
var record = (CKRecord)result[i];
var recordValue = record.ValueForKey((NSString)MyKey);
if (recordValue == null) continue;
if(!string.IsNullOrEmpty(recordValue))
return ret = recordValue;
}

How can I write multiple updates in one BulkAll method in ElasticSearch NEST 7.13.2

Using ElasticSearch NEST .Net package 7.13.2 in Visual Studio 2019
For a list of products I am currently updating existing documents in my product index by using the following code:
var productIndex = "productindex";
foreach (var product in products)
{
productClassIdScript = $"ctx._source.productClassId = \"{product.ProductClassId}\"; ";
elasticClient.Update<productIndex, object>(product.Id,
q => q.Script(s => s.Source(productClassIdScript).Lang("painless")));
}
I do this for more than 10000 products and it takes about 2 hours.
I know I can insert new documents with the Bulk API.
Can I do the updates with the BulkAll method ?
Something like this:
var bulkAllObservable = elasticClient.BulkAll<Product>(myBulkAllRequest)
.Wait(TimeSpan.FromMinutes(15), next =>
{
// do something e.g. write number of pages to console
});
How should I construct myBulkAllRequest ?
Any help is much appreciated.
Bulk index will drastically reduce your indexing / updating time, so this is a good way to go.
You can still use BulkAll for updates, in case elasticsearch already has
document with provided id, the document will be updated.
var bulk = elasticClient.BulkAll<EsDocument>(new List<EsDocument> { new EsDocument { Id = "1", Name = "1" }}, d => d);
using var subscribe = bulk.Subscribe(new BulkAllObserver(onNext: response => Console.WriteLine("inserted")));
bulk.Wait(TimeSpan.FromMinutes(1), response => Console.WriteLine("Bulk insert done"));
var bulk2 = elasticClient.BulkAll<EsDocument>(new List<EsDocument> { new EsDocument { Id = "1", Name = "1_updated" }}, d => d);
using var subscribe2 = bulk2.Subscribe(new BulkAllObserver(onNext: response => Console.WriteLine("inserted")));
bulk2.Wait(TimeSpan.FromMinutes(1), response => Console.WriteLine("Bulk insert done"));
First BulkAll will insert document with Id "1" second, will update document with Id "1".
Index state after the first bulkd
and after second one

NEST - IndexMany doesn't index my objects

I've used NEST for elasticsearch for a while now and up until now I've used the regular ElasticSearchClient.Index(...) function, but now I want to index many items in a bulk operation.
I found the IndexMany(...) function, but I must do something wrong because nothing is added to the elastic search database as it does with the regular Index(...) function?
Does anyone have any idea?
Thanks in advance!
I found the problem. I had to specifiy the index name in the call to IndexMany
var res = ElasticClient.CreateIndex("pages", i => i.Mappings(m => m.Map<ESPageViewModel>(mm => mm.AutoMap())));
var page = new ESPageViewModel
{
Id = dbPage.Id,
PageId = dbPage.PageId,
Name = dbPage.Name,
Options = pageTags,
CustomerCategoryId = saveTagOptions.CustomerCategoryId,
Link = dbPage.Link,
Price = dbPage.Price
};
var pages = new List<ESPageViewModel>() { page };
var res2 = ElasticClient.IndexManyAsync<ESPageViewModel>(pages, "pages");
This works as expected. Guess I could specify a default index name in the configuration to avoid specifying the index for the IndexMany call.
If you are using C# you should create a list of objects that you want to insert then call the IndexMany function.
Example :
List<Business> businessList = new List<Business>();
#region Fill the business list
...............................
#endregion
if (businessList.Count == 1000) // the size of the bulk.
{
EsClient.IndexMany<Business>(businessList, IndexName);
businessList.Clear();
}
And in the end check again
if (businessList.Count > 0)
{
EsClient.IndexMany<Business>(businessList, IndexName);
}

Converting MongoDB documents into c# list of objects

I am trying to write a method which would return all the Book documents from the MongoDB to my mvc application. First, I connect to database, retrieve collection and convert that collection into Json file. Next I create a list which has couple fields specified (name, author, etc.) using serializer i try to deserialize it into list and using a for loop return the list of books. Sadly I get error in the return line (convertion error). Any suggests are welcomed!
public List<Book> getAllBooks()
{
var mongoClient = new MongoClient("mongodb://localhost");
var database = mongoClient.GetDatabase("SearchForKnowledge");
var coll = database.GetCollection<BsonDocument>("Book");
coll.ToJson();
List<Book> collection = new List<Book>();
JavaScriptSerializer js = new JavaScriptSerializer();
collection = (List<Book>)Newtonsoft.Json.JsonConvert.DeserializeObject(coll.ToString());
for (int i = 0; i < collection.Count(); i++)
{
return collection[i];
}
}
well, you should try simpler way:
// add this using first
using MongoDB.Driver.Linq;
var coll = database.GetCollection<Book>("Book").AsQueryable<Book>();
And than you can do anything, e.g:
var someBooks = coll.Where(b => b.Year == 2014).Skip(0).Take(10).ToArray();
PS: You need to check out this tutorial: https://mongodb-documentation.readthedocs.org/en/latest/ecosystem/tutorial/use-linq-queries-with-csharp-driver.html

Bulk delete using Ravendb

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

Categories

Resources