C# RavenDB索引:需要一个解决方案将两个字典字段合并到一个字典中,将其展平并使其可搜索
我们正在为一个客户构建一个嵌套的UI视图,需要一个解决方案来将两个字典字段合并到一个统一的字典中,并使键可以像字段名一样进行搜索。我使用和中提到的技术创建了一个Map/Reduce索引 NameProperties–它是已知键、值对的字典。例如C# RavenDB索引:需要一个解决方案将两个字典字段合并到一个字典中,将其展平并使其可搜索,c#,ravendb,C#,Ravendb,我们正在为一个客户构建一个嵌套的UI视图,需要一个解决方案来将两个字典字段合并到一个统一的字典中,并使键可以像字段名一样进行搜索。我使用和中提到的技术创建了一个Map/Reduce索引 NameProperties–它是已知键、值对的字典。例如 "NamedProperties": [ { "Key": "Tags", "Value": "" }, { "Key": "Name", "Value": "file-184"
"NamedProperties": [
{
"Key": "Tags",
"Value": ""
},
{
"Key": "Name",
"Value": "file-184"
},
{
"Key": "Uploader",
"Value": "rmani@transper.com"
},
{
"Key": "FileType",
"Value": "Jpg"
},
{
"Key": "Language",
"Value": "English"
}]
属性–它是一个合并字典,包含MetadataProperties和NamedProperties中的键、值对
扁平属性和u是分别包含“NamedProperties”和“MetadataProperties”扁平字段值的属性。我想不出一种方法来展平计算属性,比如结合了MetadataProperties和NamedProperties字典的“Properties”。我试过海螺
以下是索引创建代码:
public class PortalEntryViews_DocumentIdSplitIndex : AbstractIndexCreationTask<PortalEntry, ViewFolderResultWithIndividualProperties>
{
public PortalEntryViews_DocumentIdSplitIndex()
{
Map = portalEntries => from portalEntry in portalEntries
select new
{
EntryId = portalEntry.Id,
MetadataProperties = portalEntry.MetaData.Select(t => new KeyValuePair<string, string>(t.Key, t.Value)).ToList(),
NamedProperties = new List<KeyValuePair<string, string>> {
new KeyValuePair<string, string>("Tags", string.Join(",", portalEntry.Tags.Where(t => !t.IsInternal).Select(t=>t.Name))),
new KeyValuePair<string, string>("Name", portalEntry.Name),
new KeyValuePair<string, string>("Uploader", portalEntry.Uploader),
new KeyValuePair<string, string>("FileType", portalEntry.FileType),
new KeyValuePair<string, string>("Language", portalEntry.Language),
new KeyValuePair<string, string>("Name", portalEntry.Name) },
Properties = new List<KeyValuePair<string, string>>(),
FlattenedProperties = "",
_ = ""
};
Reduce = results => from result in results
group result by new { result.EntryId, result.MetadataProperties, result.NamedProperties, result.FlattenedProperties, result._ } into g
select new
{
EntryId = g.Key.EntryId,
MetadataProperties = g.Key.MetadataProperties,
NamedProperties = g.Key.NamedProperties,
Properties = g.Key.MetadataProperties.Concat(g.Key.NamedProperties).ToList(),
FlattenedProperties = g.Key.NamedProperties.Select(f => CreateField(f.Key, f.Value)),
_ = g.Key.MetadataProperties.Select(t => CreateField(t.Key, t.Value, true, true))
};
}
}
我的最终目标是使用CreateField将组合字典(即Properties字段)扁平化为单个字段,可以使用键进行搜索,就好像它们是字段名一样。但是,如果我用这样的电话:
Properties=g.Key.MetadataProperties.Concatg.Key.NamedProperties.ToList.Selectt=>CreateFieldt.Key,t.Value,true,true,它似乎在运行,但当您从Ravendb Explorer查看索引时,它显示了实际错误:
阶段:索引部分:减少说明:“System.Collections.Generic.List”不包含“Select”的定义
现在,我只能将一个Dictionary MetadataProperties展平到reduce部分的“\u1”字段中,该字段可以从Ravendb Explorer和使用LuceneQuery的C代码中使用,但这不符合我的要求
有人能帮我解决这个问题吗?如果你只想搜索键值,你可以做得很简单
//the index
public class FlattenIndex: AbstractIndexCreationTask<PortalEntry>
{
public class ReduceResult
{
public string Key { get; set; }
public string Value { get; set; }
}
public FlattenIndex()
{
Map = portalEntries => from portalEntry in portalEntries
from p in portalEntry.MetadataProperties.Concat(portalEntry.NamedProperties)
select new
{
Key=p.Key,
Value=p.Value
};
}
}
//the query
using (var session = _docStore.OpenSession())
{
var someEntries = session.Query<FlattenIndex.ReduceResult, FlattenIndex>()
.Where(x => x.Key == "Language" && x.Value == "English")
.As<PortalEntry>()
.ToArray();
if (someEntries!=null)
foreach(var entry in someEntries )
{
Console.WriteLine(entry.Id);
}
}
public class PortalEntryViews_DocumentIdSplitIndex : AbstractIndexCreationTask<PortalEntry, ViewFolderResultWithIndividualProperties>
{
public PortalEntryViews_DocumentIdSplitIndex()
{
Map = portalEntries => from portalEntry in portalEntries
select new
{
EntryId = portalEntry.Id,
MetadataProperties = portalEntry.MetaData.Select(t => new KeyValuePair<string, string>(t.Key, t.Value)).ToList(),
NamedProperties = new List<KeyValuePair<string, string>> {
new KeyValuePair<string, string>("Tags", string.Join(",", portalEntry.Tags.Where(t => !t.IsInternal).Select(t=>t.Name))),
new KeyValuePair<string, string>("Name", portalEntry.Name),
new KeyValuePair<string, string>("Uploader", portalEntry.Uploader),
new KeyValuePair<string, string>("FileType", portalEntry.FileType),
new KeyValuePair<string, string>("Language", portalEntry.Language),
new KeyValuePair<string, string>("Name", portalEntry.Name) },
Properties = new List<KeyValuePair<string, string>>(),
FlattenedProperties = "",
_ = ""
};
Reduce = results => from result in results
group result by new { result.EntryId, result.MetadataProperties, result.NamedProperties, result.FlattenedProperties, result._ } into g
select new
{
EntryId = g.Key.EntryId,
MetadataProperties = g.Key.MetadataProperties,
NamedProperties = g.Key.NamedProperties,
Properties = g.Key.MetadataProperties.Concat(g.Key.NamedProperties).ToList(),
FlattenedProperties = g.Key.NamedProperties.Select(f => CreateField(f.Key, f.Value)),
_ = g.Key.MetadataProperties.Select(t => CreateField(t.Key, t.Value, true, true))
};
}
}
var entries =
session.Advanced.LuceneQuery<ViewFolderResultWithIndividualProperties>(
"PortalEntryViews/DocumentIdSplitIndex")
.WhereEquals("Language", "English").ToList();
Raven.Imports.Newtonsoft.Json.JsonSerializationException : Could not read value for property: FlattenedProperties ----> Raven.Imports.Newtonsoft.Json.JsonReaderException : Error reading string. Unexpected token: StartArray
//the index
public class FlattenIndex: AbstractIndexCreationTask<PortalEntry>
{
public class ReduceResult
{
public string Key { get; set; }
public string Value { get; set; }
}
public FlattenIndex()
{
Map = portalEntries => from portalEntry in portalEntries
from p in portalEntry.MetadataProperties.Concat(portalEntry.NamedProperties)
select new
{
Key=p.Key,
Value=p.Value
};
}
}
//the query
using (var session = _docStore.OpenSession())
{
var someEntries = session.Query<FlattenIndex.ReduceResult, FlattenIndex>()
.Where(x => x.Key == "Language" && x.Value == "English")
.As<PortalEntry>()
.ToArray();
if (someEntries!=null)
foreach(var entry in someEntries )
{
Console.WriteLine(entry.Id);
}
}