I'm asking my question here because I didn't find any answer in the RavenDB's online documentation.
However, my question is quite simple : can we query a non saved document in the same session that the document has been stored ?
using( var session = store.OpenSession() )
{
session.Store( new SampleObject() { Name = "My name is sample" } );
var sample = (from o in session.Query<SampleObject>()
where o.Name = "My name is sample").FirstOrDefault();
}
sample will be null ?
Do I have to use "Customize" method on the query to load non stale data ?
Thanks for you help.
The new document wasn't transmitted to the database yet, you have to call session.SaveChanges() before querying. Additionally you have to customize your query to wait for the index to catch the new documents, but you've spotted that already.
Related
I currently have a ravenDB database with a model that has a specific set of fields that I have been working with. I realized there is a field or two that I need to add and have successfully used ravenDB's patch request once to patch my documents in my database to initialize those fields on all the pre existing documents. I wanted to add another field again but I cannot get the patch code to run again to update my documents another time. I was wondering if someone could tell me if there was any documentation or methods to check the database at deploy and see if the models are the same, if not to patch the ones that are not but leave the ones that are alone and ensure after an update the pre existing models are not reset to what the patch is patching.
private void updateDb(IDocumentStore store)
{
store.DatabaseCommands.UpdateByIndex("Interviews_ByCandidateInterviewAndDate",
new IndexQuery{
Query = "Candidate:"
},
new []{
new PatchRequest{
Type = PatchCommandType.Set,
Name = "IsArchived",
Value = true
},
new PatchRequest{
Type = PatchCommandType.Set,
Name = "ArchiveDate",
Value = null
},
new PatchRequest{
Type = PatchCommandType.Set,
Name = "TestingField",
Value = 14
}
},
new BulkOperationOptions
{
AllowStale = false
}
);
}
The first two patch requests went through and shows up in the database but one thing I cannot see is if i were to run this patch again to get that third field into the model, would it change all the values that are already existing in the database for the first two to true and null or would it leave them the way they are and more importantly, I cannot get this code to run again.
Any pointers in the right direction would be greatly appreciated! thanks.
You query is wrong:
Query = "Candidate:"
Should have no results (invalid query).
Use:
Query = "Candidate:*"
My Scenario:
I have a few thousand documents that I want alter (rename & add properties), I have written a a PatchRequest to alter the document but this takes a document Id.
I'm looking for a way to get a list of document Id's for all documents of a specific type, any ideas?
If possible I'd like to avoid retrieving the document from the server.
I have written a PatchRequest to alter the document but this takes a document Id.
No, .Patch takes a document ID, not the PatchRequest.
Since you want to update a whole swath of documents, you'll want to use the .UpdateByIndex method:
documentStore.DatabaseCommands.UpdateByIndex("IndexName",
new IndexQuery {Query = "Title:RavenDB"},
new []
{
new PatchRequest
{
Type = PatchCommandType.Add,
Name = "Comments",
Value = "New automatic comment we added programmatically"
}
}, allowStale: false);
This will allow you to patch all documents matching an index. That index can be whatever you please.
For more information, see Set-Based Operations in the Raven docs.
I want to add property to existing document (using clues form http://ravendb.net/docs/client-api/partial-document-updates). But before adding want to check if that property already exists in my database.
Is any "special,proper ravendB way" to achieve that?
Or just load document and check if this property is null or not?
You can do this using a set based database update. You carry it out using JavaScript, which fortunately is similar enough to C# to make it a pretty painless process for anybody. Here's an example of an update I just ran.
Note: You have to be very careful doing this because errors in your script may have undesired results. For example, in my code CustomId contains something like '1234-1'. In my first iteration of writing the script, I had:
product.Order = parseInt(product.CustomId.split('-'));
Notice I forgot the indexer after split. The result? An error, right? Nope. Order had the value of 12341! It is supposed to be 1. So be careful and be sure to test it thoroughly.
Example:
Job has a Products property (a collection) and I'm adding the new Order property to existing Products.
ravenSession.Advanced.DocumentStore.DatabaseCommands.UpdateByIndex(
"Raven/DocumentsByEntityName",
new IndexQuery { Query = "Tag:Jobs" },
new ScriptedPatchRequest { Script =
#"
this.Products.Map(function(product) {
if(product.Order == undefined)
{
product.Order = parseInt(product.CustomId.split('-')[1]);
}
return product;
});"
}
);
I referenced these pages to build it:
set based ops
partial document updates (in particular the Map section)
I am new to raven db. I have read the API and try to create a database . It has something like EnsureDatabaseExists function which creates the database if it does not exist. It actually uses DocumentDatabase type to create that database. I use it and it creates the database but I want to use this object directly so that using this object I can directly work with documents. Am i doing right? Or can there be any better approach then this to work with documents.Thank you.
I think you're confusing the database document and querying documents.
The database document is a document on the default database, which just represent a database in RavenDB which is not the default database. It stores some data like the database name and location. You, as a consumer of ravendb as nothing to do with this document. And this has nothing to do with querying any other documents.
Look here in order to learn how to query ravendb for documents. In order to query a specific database, if you work just with that database than you better just specify the database name in the connection string. If you work against multiy databases at once, you can specify the database name that you want when you open a session, store.OpenSession("database-name").
Three methods are available on store.DatabaseCommands.GlobalAdmin.
GetDatabaseNames: lists database names
EnsureDatabaseExists: creates database if it does not exists
CreateDatabase: creates database
Note that DocumentStore.Initialize() already ensures that the database is created. You can pass a boolean false to avoid this behavior.
// init store object, you pass the service URL + the database name
var store = new DocumentStore("http://localhost:8001/databases/MyNewDataBase");
store.Initialize(false);
// most simple thing is:
var dbName = store.DefaultDatabase;
store.DatabaseCommands.GlobalAdmin.EnsureDatabaseExists(dbName);
If you want to check without creating:
// there is a method to list the database names
bool exists = false;
for (int i = 0; i < int.MaxValue; i++)
{
var names = store.DatabaseCommands.GlobalAdmin.GetDatabaseNames(100, i * 100);
if (names.Contains(dbName))
{
exists = true;
break;
}
if (names.Length < 100)
{
// no more databases
break;
}
}
if (exists)
{
// database exists, do something
}
Reference: https://ravendb.net/docs/article-page/3.5/Csharp/client-api/commands/how-to/create-delete-database
rI've looked at the questions and indeed the RavenDb docs. There's a little at RavenDb Index Replication Docs but there doesn't seem any guidance on how/when/where to create the IndexReplicationDestination
Our use case is very simple (it's a spike). We currently create new objects (Cows) and store them in Raven. We have a couple of queries created dynamically using LINQ (e.g. from c in session.Query<Cows> select c).
Now I can't see where I should define the index to replicate. Any ideas? I've got hold of the bundle and added it to the server directory (I'm assuming it should be in RavenDB.1.0.499\server\Plugins where RavenDB.1.0.499\server contains Raven.Server.exe)
Edit: Thanks Ayende... the answer below and in the ravendb groups helped. There was a facepalm moment. Regardless here's some detail that may help someone else. It really is very easy and indeed 'just works':
a) Ensure that the plugins are being picked up. You can view these in the statistics - available via the /localhost:8080/stats url (assuming default settings). You should see entries in 'Extensions' regarding to the IndexReplication bundle.
If not present ensure the versions of the DLLs (bundle and server) are the same
b) Ensure the index you want to replicate has been created. They can be created via Client API or HTTP API.
Client API:
public class Cows_List : AbstractIndexCreationTask<Cow>
{
public Cows_List()
{
Map = cows => from c in cows select new { c.Status };
Index( x => x.Status, FieldIndexing.Analyzed);
}
}
HTTP API (in studio):
//Cows/List
docs.Cows
.Select(q => new {Status = q.Status})
c) create the replication document. The clue here is DOCUMENT. Like everything stored, it too is a document. So after creating it must be stored in the Db :
var replicationDocument = new Raven.Bundles.IndexReplication.Data.IndexReplicationDestination
{
Id = "Raven/IndexReplication/Cows_List", ColumnsMapping = { {"Status", "Status"} },
ConnectionStringName = "Reports", PrimaryKeyColumnName = "Id",
TableName = "cowSummaries"
};
session.Store(replicationDocument);
sesson.SaveChanges();
d) Ensure you have the following in the CLIENT (e.g. MVC app or Console)
e) Create the RDBMS schema. I have a table in 'cowReports' :
CREATE TABLE [dbo].[cowSummaries](
[Id] nvarchar NULL,
[Status] nchar NULL)
My particular problem was not adding the index document to the store. I know. facepalm. Of course everything is a document. Works like a charm!
You need to define two things.
a) An index that transform the document to the row shape.
b) A document that tell RavenDB what is the connection string name, the table name, and the columns to map