How to create RavenDB index for linked documents - ravendb

I have the following design: Debtors are managed by Agents. Each are stored as independent documents, with id-based references to one-another. Each communication between an Agent and his debtors is recorded as 3rd independent document, with an id-based reference to the debtor. It is thus easy to create an index CommunicationsByDebtor, as follows:
from c in docs.Communications
select new { c.DebtorId }
However, how do I get define the map for an index CommunicationsByAgent?
I've tried this, but it don't compile:
from c in docs.Communications
from d in docs.Debtors
where d.Id == c.Communication_Debtor
select new { d.AgentId }
Any advice would be appreciated.

from c in docs.Communications
let d = LoadDocument<Debtor>(c.Communication_Debtor)
select new { d.AgentId }
Reference: Indexing Related Documents

Related

How to achieve backref-like query in Node.js and sqlite?

Short Version: Is there an application in Node.js that offers functionalities similar to Python-SQLAlchemy's backref?
What I actually want to achieve:
I have three sql tables: article, chapter and subchapter. One article has multiple chapters, and on chapter can contain multiple or zero subchapter.
With SQLAlchemy it's quite simple, in models.py
class Article(db.Model):
...
chapters = db.relationship('Chapter', backref='mainArticle', lazy=True)
class Chapter(db.Model):
...
articleID = db.Column(db.Integer, db.ForeignKey('article.id'), nullable=False)
subChapters = db.relationship('subChapter', backref='mainChapter', lazy=True)
class subChapter(db.Model):
...
chapterID = db.Column(db.Integer, db.ForeignKey('chapter.id'), nullable=False)
And then I can access even the attributes of Article from subChapter:
subchapter = subChapter.query.first()
subchapter.mainChapter.id # Returns the chapter ID
subchapter.mainChapter.mainArticle.id # Returns the article ID
I've been using SQLAlchemy so I'm not sure how to select with SQLite, I tried:
app.get('/test/:articleID', (req, res) => {
let article_id = req.params.articleID;
let sql = `SELECT article.*, chapter.*, subchapter.*
FROM article
LEFT JOIN chapter ON article.id = chapter.articleID
LEFT JOIN subchapter ON chapter.id = subchapter.chapterID
WHERE article.id = ?`;
db.get(sql, [article_id], (err, article) => {
res.send(article)
});
})
But it just spit out a bunch of null...
Unfortunately current situation forces me to use Node.js instead of Python, so is there any way to achieve a similar result in Node.js?
Ok after some trials and errors I figured out a not-so-elegant way (maybe an ugly way) to get the job done without any third-party application.
First we select ALL the rows of the database that are linked to a article number with LEFT JOIN method. The null problem seems to be caused by identical key name in different tables (i.e. article.title, chapter.title, subchapter.title), so just distinguish them with AS method.
SELECT article.title,
chapter.title AS cT, chapter.chapterNumber AS cN,
subchapter.title AS scT, subchapter.subChapterNumber AS scN
FROM article
LEFT JOIN chapter ON article.id = chapter.articleID
LEFT JOIN subchapter ON chapter.id = subchapter.chapterID
WHERE article.id = 1
ORDER BY
chapterNumber ASC,
subChapterNumber ASC
This will get a bunch of entries where every subchapter is shown once, every chapter is shown at least once, depending on the subchapters it has.
Now we can write an iteration to sort the data. The fundamental idea is to form an article object, with a chapter property that contains an array of chapter objects, each one contains a subchapter property populated with an array of its own subchapter objects:
article = {
"title": "Article Title",
"chapters": [
{
"chapterNumber": 1,
"subchapters": [
{
"subchapterNumber": 1,
},
{
"subchapterNumber": 2,
}
]
},
{
"chapterNumber": 2,
"subchapters": []
},
]
}
Then we can simply use article.chapters[0] to access the chapter 1, and use article.chapters[0].subchapters[0] to get chapter 1.1.
To achieve this, the iteration to organise the data would be:
article = {"title":entries[0].title, "chapters":[]};
// First create all the chapter entries for subchapters to depend on.
for (i in entries) {
// Use underscore.js utility to determine if this chapter has already been put in.
if (_.findWhere(article.chapters, {"chapterNumber":entries[i].cN}) == null) {
// Create a new chapter entry.
article.chapters.push({"chapterNumber":entries[i].cN, "subchapters":[]})
}
};
// Then put in place all the subchapters.
for (i in entries) {
// Only analyse all the entries that contain a subchapter.
if (entries[i].scN){
// Find the corresponding chapter
chapter = _.findWhere(article.chapters, {"chapterNumber":entries[i].cN})
// Determine if this subchapter has already been put in.
if (_.findWhere(chapter.subchapters, {"subchapterNumber":entries[i].scN}) == null) {
// Create a new subchapter entry.
chapter.subchapters.push({"chapterNumber":entries[i].cN, "subchapterNumber":entries[i].scN})
}
}
};
The same principal still applies if the database is more complicated, like if every subchapter contains zero to multiple secondary subchapters.
Now a single article object contains all the informations we can possibly need to display an article in its order. A simple run with pug to display the schema would be:
html
head
title= article.title
body
each chapter in article.chapters
li= chapter.title
each subchapter in chapter.subchapters
li(style="padding-left:30px")= subchapter.title
This might not be quite efficient, but it at least get the job done. Please tell me if you know any better solution. Happy coding to everyone!

How to retrieve a list of document names linked to a given index in apache chemistry opencmis

I was trying to retrieve a list of document names linked to a given index id (in my example "index-80") with the code below:
Note: The code below uses .Net but I can use java too.
IObjectId id = session.CreateObjectId("index-80");
IFolder indexFolder = session.GetObject(id) as IFolder;
foreach (ICmisObject cmisObject in indexFolder.GetChildren())
{
Console.WriteLine(cmisObject.Name);
}
The issue is, the code will return only children indexes ("index-80" is parent of a couple of nested indexes in our CMIS repository) but it won't return documents linked to it.
After a bit of reading, it seems that documents are children of the ROOTFOLDER, but not of an indexentry. That will explain why the code above won't work.
How can I retrieve all document names linked to a given index in apache chemistry opencmis?

Using inline sql with entity frame work and c#

We are having som performance issue with EF and I want to try rewrite a query to inline sql. However I am having some difficulties, it is probably just a noob issue.
Lets say I have 3 classes: License, GroupLicense and Product
public class License
{
//stuff
Product MyProduct{get;set}
}
public class GroupLicense:License
{
// more stuff
}
public class Product
{
//product info stuff
}
Now I need to fetch some Grouplicenses depending on some requirements. However doing it with the datacontext and linq takes 2 minutes.
Something similar to this
var institutionLicenses = db.GroupLicenses
.Include(lic => lic.Product).Where(x => productIds.Contains(x.Product.Id) && x.LicenseStatus == StatusEnum.Active).ToList();
I want to do the same query using inline sql similar to this: I join the tables so all the primitive fields are okay.
var gl = db.Database.SqlQuery<GroupLicense>("select * from GroupLicense as g left join Licenses on g.Id =Licenses.Id").ToList();
(It is just example code - I know it is not working :))
However when executing, The base product property on License is null, all the primitive fields are there.
What do I need to change in my sql statement to make it work?

azure custom api include sub properties

I have a question how to build a custom api script that returns sub objects from related tables.
My table structure looks like this ( I'm not allowed to upload an Image :-( ).
My script looks like this (SQL is much much more complex, I make it short for my question):
exports.get = function(request, response) {
var sql = "SELECT * FROM [PointsOfInterests] ";
request.service.mssql.query(sql, [],{
success: function(results)
{
response.send(statusCodes.OK, results);
}
});
};
My question now is how to include the property "address" to the result?
My reslut object shoud look like this:
[
{
id: 123,
address:
{
City: test
}
}
]
Thanks for your help!
I understand that your question refers to Windows Azure Mobile Services.
You can do this using a custom API. See Define custom APIs in Windows Azure Mobile Services.
Use a SQL query that uses joints to return the data you need from both tables. See Join Fundamentals and Using Inner Joins to learn the syntax.
For instance, you could use a query such as:
select a.Id, a.Name, a.Location, b.City, b.PLZ, b.Street
from PointsOfInterest as a
inner join Address as b
on a.AddressId = b.ID
and then create a JavaScript object from the result set, with the structure your response message needs.
You might also need to use a left outer join if there are records in "a" which are not related to any records in "b" (optional relationship).

How do I install and setup the RavenDb index replication

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