transforming foreign constraints in raven document db - ravendb

I have following entity "MyEntity" in my RavenDb
{
Id: {Guid}
//...
//...
}
In the application there might occur a specific event relating to elements of MyEntity.
Not I want to associate users (also in db of course) with this type of event in order to allow the eventhandler to handle the event only if there is a relation between MyEntity and User
Using MySQL I'd create a table which which aggregates MyEntity.Id with User.Id (and possibly a specific EventId) 1:x (x element N) so that I can query all items with a a specific Id (MyEntitiy.Id) and the corresponding User.Id
Is it okay to simply apply this approach to a document db like RavenDb? Or should I consider something else?

Relations between documents in RavenDB is implemented in the following way:
A document can reference any other document from the database by storing the referenced document ID in the document. Referenced documents are called: Related Documents.
For example, document employees/3-A is referring to document employees/2-A:
{
"LastName": "Leverling",
"FirstName": "Janet",
"ReportsTo": "employees/2-A",
}
These related documents can be 'loaded', 'indexed' & 'queried on'.
Learn more about document Modeling & working with multiple documents in the following links:
Document Modeling
Working with multiple documents
Handle Document Relationships

Related

How to build Parent and Child Collection Elements / Tree View in Directus?

Do you know a way to build parent-child-relations in Directus, ideally with some kind of tree display? Like, for example, to define category trees or page trees, with parent pages and child pages. It is a very common functionality in most of the famous CMS, and I wonder how to build that in Directus.
I've found the "Tree View" field, but I don't really understand how it works, there is no documentation on it and I get error messages like
{
"errors": [
{
"message": "alter table `Unterkategorien` add constraint `unterkategorien_name_foreign` foreign key (`name`) references `Kategorien` (`id`) on delete SET NULL - ER_CANNOT_ADD_FOREIGN: Cannot add foreign key constraint",
"extensions": {
"code": "INTERNAL_SERVER_ERROR"
}
}
]
}
Any hint is appreciated! Thanks!
Directus: 9.13.1 (self hosted on Ubuntu/Coolify)
DB: MySQL 5.7
I've found a short video showing how to properly use the "Tree View" field: https://github.com/directus/directus/issues/14378#issuecomment-1181416141
In short, with tree view you need to choose the same collection and type in (not select!) a new field name for the foreign key (like, for example "parent").
You then should be able to select entries of the same collection within the edit form of one entry, thus in effect creating "children" of that entry. This is neatly represented also in the API and very helpful for building nested content.
I understand that it's still limited on the display end of things. A real tree view display is apparently on the Directus roadmap: https://directus.io/road-map/

How to filter fields in documents with security rules

I am experimenting with Cloud Firestore security rules. Is it possible to filter document fields?
For example if you have a document
{
name: "John Doe",
email: "doe#example.com"
}
then some users aren't allowed to get the document with the email address. Their application requests the document with
firebase.firestore.doc('users/doe-uid')
and gets this document
{
name: "John Doe",
}
If yes, how?
I think it should be possible because the Cloud Firestore Security Rules Reference says in the first sentence (emphasis is mine):
Cloud Firestore Security Rules are used to determine who has read and write access to collections and documents stored in Cloud Firestore, as well as how documents are structured and what fields and values they contain.
However I couldn't find anything in the reference telling me how to filter out fields.
Firestore rules are not filters, they're a server-side validation of document queries, meaning that you access (or not) the whole document, not particular fields.
The piece of documentation you mentionned means that you can do data validation on fields.
Here is a basic example of rules validating data on a write query (via request.resource.data) :
match /users/{userId} {
allow write: if request.resource.data.age is int;
}
Here is another basic example that uses an existing field to validate a read query (via resource.data) :
match /articles/{articleId} {
allow read: if resource.data.isPublished == true;
}
To filter out fields, you have do it client side, after the query.
Now If you want to secure access to certain fields, you have to create another collection (look into subcollections) with a different set of rules, and make another query that will match these rules.

find nodes with a specific child association

I am looking for a query (lucene, fts-alfresco or ...) to return all the document which have a specific child association (that is not null).
Some context:
Documents of type abc:document have a child-association abc:linkedDocument.
Not all document have an other document linked to them, some have none some have one or multiple.
I need a fast and easy way to get an overview of all the documents that do have at least one document linked to them.
Currently I have a webscript that does what I need, but prefer not to have tons of webscripts which are not business related.
code:
SearchParameters sp = new SearchParameters();
String query = "TYPE:\"abc:document\"";
StoreRef store = StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
sp.addStore(store);
sp.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO);
sp.setQuery(query);
ResultSet rs = services.getSearchService().query(sp);
List<NodeRef> nodeRefs = rs.getNodeRefs();
for (NodeRef ref : nodeRefs) {
List<ChildAssociationRef> refs = services.getNodeService().getChildAssocs(ref);
for(ChildAssociationRef chref : refs){
if(chref.getQName().equals(AbcModel.ASSOC_LINKED_DOC)){
logger.debug("Document with linked doc: {}", ref);
break;
}
}
}
Associations aren't query-able so you'll have to do what you are doing, which is essentially checking every node in a result set for the presence of a desired association.
The only improvement I can suggest is that you can ask for the child associations of a specific type which would prevent you from having to check the type of every child association, see How to get all Child associations with a specific Association Type Alfresco (Java)

In RavenDB can I retrieve all document Id's for a document type

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.

RavenDB Index created incorrectly

I have a document in RavenDB that looks looks like:
{
"ItemId": 1,
"Title": "Villa
}
With the following metadata:
Raven-Clr-Type: MyNamespace.Item, MyNamespace
Raven-Entity-Name: Doelkaarten
So I serialized with a type MyNamespace.Item, but gave it my own Raven-Entity-Name, so it get its own collection.
In my code I define an index:
public class DoelkaartenIndex : AbstractIndexCreationTask<Item>
{
public DoelkaartenIndex()
{
// MetadataFor(doc)["Raven-Entity-Name"].ToString() == "Doelkaarten"
Map = items => from item in items
where MetadataFor(item)["Raven-Entity-Name"].ToString() == "Doelkaarten"
select new {Id = item.ItemId, Name = item.Title};
}
}
In the Index it is translated in the "Maps" field to:
docs.Items
.Where(item => item["#metadata"]["Raven-Entity-Name"].ToString() == "Doelkaarten")
.Select(item => new {Id = item.ItemId, Name = item.Title})
A query on the index never gives results.
If the Maps field is manually changed to the code below it works...
from doc in docs
where doc["#metadata"]["Raven-Entity-Name"] == "Doelkaarten"
select new { Id = doc.ItemId, Name=doc.Title };
How is it possible to define in code the index that gives the required result?
RavenDB used: RavenHQ, Build #961
UPDATE:
What I'm doing is the following: I want to use SharePoint as a CMS, and use RavenDB as a ready-only replication of the SharePoint list data. I created a tool to sync from SharePoint lists to RavenDB. I have a generic type Item that I create from a SharePoint list item and that I serialize into RavenDB. So all my docs are of type Item. But they come from different lists with different properties, so I want to be able to differentiate. You propose to differentiate on an additional property, this would perfectly work. But then I will see all list items from all lists in one big Items collection... What would you think to be the best approach to this problem? Or just live with it? I want to use the indexes to create projections from all data in an Item to the actual data that I need.
You can't easily change the name of a collection this way. The server-side will use the Raven-Entity-Name metadata, but the client side will determine the collection name via the conventions registered with the document store. The default convention being to use the type name of the entity.
You can provide your own custom convention by assigning a new function to DocumentStore.Conventions.FindTypeTagName - but it would probably be cumbersome to do that for every entity. You could create a custom attribute to apply to your entities and then write the function to look for and understand that attribute.
Really the simplest way is just to call your entity Doelkaarten instead of Item.
Regarding why the change in indexing works - it's not because of the switch in linq syntax. It's because you said from doc in docs instead of from doc in docs.Items. You probably could have done from doc in docs.Doelkaartens instead of using the where clause. They are equivalent. See this page in the docs for further examples.