我有一个项目,我有一组表格:
public class Form
{
public string Id { get; set; }
public string Name { get; set; }
public IList<string> FieldValueIds { get; set; }
public string UserId { get; set; } // the user who completed the form.
public string FormTemplateId { get; set; }
}
每个&#34;实施&#34;在创建表单时选择的表单模板。
public class FormTemplate
{
public string Id { get; set; }
public string Name { get; set; }
public IList<string> FieldIds { get; set; }
}
定义表单中存在哪些字段。每个字段
public class FormField
{
public string Id { get; set; }
public string Name { get; set; }
public string Caption { get; set; }
public ValueType DataType { get; set; } // Enum specifying the type of data this field accepts.
}
存储有关该字段的信息,例如描述和期望的类型。每个FormField都可以存在于多个FormTemplates中,表单的值存储为与Form本身相关的FieldValue对象。
public class FieldValue
{
public string Id { get; set; }
public string FieldId { get; set; }
public string ValueAsJsonString { get; set; }
}
其他对象包括用户对象:
public class User
{
public string Id { get; set; }
public string Username { get; set; }
public string GivenNames { get; set; }
public string Surname { get; set; }
}
我希望能够执行查询以查找具有指定名称的用户完成的所有表单,或者查找名称为X的字段具有值Y的所有表单,依此类推。
我已经研究了文档Indexing related documents中指定的索引用法,但是当我按如下方式实现示例时,文档中提供的实现引发了NotSupportedException:
class FormTemplates_ByFieldAndName : AbstractIndexCreationTask<FormTemplate>
{
public class Result
{
public string Name { get; set; }
public IList<string> FieldNames { get; set; }
}
public FormTemplates_ByFieldAndName()
{
Map = FormTemplates => from FormTemplate in FormTemplates
select new
{
Name = FormTemplate.Name,
FieldNames = FormTemplate.FieldIds.Select(x => LoadDocument<FormField>(x).Name)
};
}
}
// in code:
IList<FormTemplate> TestResults = session.Query<FormTemplates_ByFieldAndName.Result, FormTemplates_ByFieldAndName>()
.Where(x => x.Name == "TemplateName" || x.FieldNames.Contains("FieldName"))
.OfType<FormTemplate>()
.ToList();
尽管我可以说这是正确实现的,但是我已经看到了用.Any实现替换.Contains的建议。取而代之的是,我一直在通过应用连续的.Where参数来尝试不同的方法。像这样:
var pre = session.Query<FormTemplates_ByFieldAndName.Result, FormTemplates_ByFieldAndName>();
var pr2 = pre.Where(x => x.Name == "TypeTest25");
List<FormTemplate> TestResults = pr2
.Where(x => x.FieldNames.Any(a => a == "field25"))
.OfType<FormTemplate>()
.OrderByScoreDescending()
.ToList();
通过以预先指定的格式应用基于提供的字符串的连续过滤器,修改系统以更加面向工厂的方式执行。
这是我应该采用的方式,如果不是我应该改变什么?特别是如果我要继续使用Indexing选项,我将如何通过FormTemplates将此技术应用于Forms和FormFields之间的嵌套关系。
答案 0 :(得分:0)
你似乎试图以一种主要是关系的方式来做这件事,但你不必这样做。
不要试图拥有一组每个都包含部分数据的独立文档,而只是将它们存储在一个文档中。
{
"Id": "forms/1234",
"Name": "Tom",
"FieldValues": [
{
"Id": "FromValues/SchoolDistrictName",
"Value": "ABi195"
}
],
"UserId": "users/tom",
"FormTemplateId": "FromTemplate/1234"
}
这将生成如下所示的文档:
{ "food": {
"apple": {
"color": "red"
},
"orange": {
"color": "orange"
},
"potato": {
"color": "brown"
},
"tomato": {
"color": "red"
}
}
}
这是一种更自然的建模方式。 此时,您可以使用RavenDB的动态数据索引功能,请参阅此处的文档:
https://ravendb.net/docs/article-page/3.5/Csharp/indexes/using-dynamic-fields