public Record GetItemById(string id, RecordFormat format) { return(_mapper.Map <RecordWithInverses>(_store.GetRecord(_store.CodeEntity(id)), options => options.Items["Format"] = format)); }
// Новая реализация загрузки базы данных private void FillDb(IEnumerable <FogInfo> fogFlow) { // Пока каждый раз чистим базу данных Store.Clear(); // Вычисление "важных" кодов var codRdftype = Store.CodeEntity("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); // Зафиксирован? 0; // Готовим битовый массив для отметки того, что хеш id уже "попадал" в этот бит int rang = 24; // пока предполагается, что число записей (много) меньше 16 млн. int mask = ~((-1) << rang); int baVolume = mask + 1; System.Collections.BitArray bitArr = new System.Collections.BitArray(baVolume); // Хеш-функция будет ограничена rang разрядами, массив и функция нужны только временно int Hash(string s) => s.GetHashCode() & mask; // Словарь, фиксирующий максимальную дату для заданного идентификатора, первая запись не учитывается Dictionary <string, DateTime> lastDefs = new Dictionary <string, DateTime>(); // Первый проход сканирования фог-файлов. В этом проходе определяется набор повторно определенных записей и // формируется словарь lastDefs foreach (FogInfo fi in fogFlow) { switch (fi.Vid) { // Чтение фога case ".fog": { fi.Fogx = XElement.Load(fi.Pth); foreach (XElement xElement in fi.Fogx.Elements()) { XElement record = ConvertXElement(xElement); // Обработаем "странные" delete и replace if (record.Name == ONames.fogi + "delete") { string idd = record.Attribute(ONames.rdfabout)?.Value ?? record.Attribute("id")?.Value; // Если нет атрибута mT, временная отметка устанавливается максимальной, чтобы "забить" другие отметки string mTvalue = record.Attribute("mT") == null ? DateTime.MaxValue.ToString(CultureInfo.InvariantCulture) : record.Attribute("mT")?.Value; CheckAndSet(bitArr, Hash, lastDefs, idd, mTvalue); continue; } if (record.Name == ONames.fogi + "substitute") { continue; // пока не обрабатываем } string id = record.Attribute(ONames.rdfabout)?.Value; CheckAndSet(bitArr, Hash, lastDefs, id, record.Attribute("mT")?.Value); } fi.Fogx = null; break; } case ".fogp": break; } } // Второй проход сканирования фог-файлов. В этом проходе, для каждого фога формируется поток записей в // объектном представлении, потом этот поток добавляется в store foreach (FogInfo fi in fogFlow) { switch (fi.Vid) { // Чтение фога case ".fog": case ".fogx": { fi.Fogx = XElement.Load(fi.Pth); IEnumerable <object> flow = fi.Fogx.Elements() .Select(xrec => ConvertXElement(xrec)) // Обработаем delete и replace. delete доминирует (по времени), но в выходной поток ничего не попадает // substitute - не обрабатываем .Where(record => record.Name != ONames.fogi + "delete" && record.Name != ONames.fogi + "substitute") // Отфильтруем записи с малыми временами. т.е. если идентификатор есть в словаре, но он меньше. // Если он больше, то не фильтруем, а словарный вход корректируем .Where(record => { var xAbout = record.Attribute(ONames.rdfabout); if (xAbout == null) { return(true); } string id = xAbout.Value; if (!lastDefs.ContainsKey(id)) { return(true); } DateTime mT = DateTime.MinValue; string mTvalue = record.Attribute("mT")?.Value; if (mTvalue != null) { mT = DateTime.Parse(mTvalue); } DateTime last = lastDefs[id]; if (mT < last) { return(false); // пропускаем } if (mT == last) { return(true); // берем } // if(mT > last) // берем и корректируем last { lastDefs.Remove(id); lastDefs.Add(id, mT); return(true); } }) .Select(record => { string id = record.Attribute(ONames.rdfabout).Value; int rec_type = Store.CodeEntity(ONames.fog + record.Name.LocalName); int id_ent = Store.CodeEntity(id); object[] orecord = new object[] { id_ent, (new object[] { new object[] { codRdftype, rec_type } }).Concat( record.Elements().Where(el => el.Attribute(ONames.rdfresource) != null) .Select(subel => { int prop = Store.CodeEntity( subel.Name.NamespaceName + subel.Name.LocalName); return(new object[] { prop, Store.CodeEntity(subel.Attribute(ONames.rdfresource).Value) }); })).ToArray(), record.Elements().Where(el => el.Attribute(ONames.rdfresource) == null) .Select(subel => { int prop = Store.CodeEntity(subel.Name.NamespaceName + subel.Name.LocalName); return(new object[] { prop, subel.Value }); }) .ToArray() }; return(orecord); }); Store.Load(flow); fi.Fogx = null; break; } case ".fogp": break; } } Store.Build(); Store.Flush(); GC.Collect(); }
public TripleStoreProfile(TripleRecordStore store) { _store = store; // Вычисление "важных" кодов cod_rdftype = store.CodeEntity("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); // Зафиксирован? 0; cod_delete = store.CodeEntity("http://fogid.net/o/delete"); cod_name = store.CodeEntity("http://fogid.net/o/name"); CreateMap <object, RecordField>().ConstructUsing((triples, context) => { if (!(triples is object[] dup)) { return(null); } return(new RecordField() { Property = store.Decode((int)dup[0]), Value = (string)dup[1] }); }); CreateMap <object, RecordProperty>().ConstructUsing((triples, context) => { if (!(triples is object[] dup)) { return(null); } return(new RecordProperty() { Property = store.DecodeEntity((int)dup[0]), Value = new Record() { Id = store.DecodeEntity((int)dup[1]) } }); }); CreateMap <object, RecordInverseProperty>().ConstructUsing((source, context) => { if (!(source is object[] triples)) { return(null); } int cid = (int)triples[0]; object[] found = ((object[])triples[1]).Cast <object[]>().FirstOrDefault(dup => (int)dup[1] == cid); return(new RecordInverseProperty() { Property = store.DecodeEntity((int)found[0]), Value = new Record() { Id = store.DecodeEntity((int)triples[0]) } }); }); CreateMap <object, Record>().ConstructUsing((source, context) => { if (!(source is object[] triples)) { return(null); } if (context.Options.Items["Format"] is RecordFormat format) { //todo use format recursive return(new Record() { Id = store.DecodeEntity((int)triples[0]), Type = GetRecordType(source), Fields = context.Mapper.Map <RecordField[]>(((object[])triples[2])), Directs = context.Mapper.Map <RecordProperty[]>((object[])triples[1]) }); } return(new Record() { Id = store.DecodeEntity((int)triples[0]), Type = GetRecordType(source), Fields = context.Mapper.Map <RecordField[]>((object[])triples[2]), Directs = context.Mapper.Map <RecordProperty[]>((object[])triples[1]) }); }); CreateMap <object, RecordWithInverses>().ConstructUsing((source, context) => { if (!(source is object[] triples)) { return(null); } return(new RecordWithInverses() { Id = store.DecodeEntity((int)triples[0]), Type = GetRecordType(source), Fields = context.Mapper.Map <RecordField[]>((object[])triples[2]), Directs = context.Mapper.Map <RecordProperty[]>((object[])triples[1]), Inverses = context.Mapper.Map <IEnumerable <RecordInverseProperty> >(store.GetRefers((int)triples[0])) ?.ToArray() }); }); CreateMap <Record, XElement>().ConvertUsing((record, context) => { if (record == null) { return(null); } XElement xres = new XElement("record", new XAttribute("id", record.Id), record.Type == null ? null : new XAttribute("type", record.Type), record.Fields?.Select(dup => new XElement("field", new XAttribute("prop", dup.Property), dup.Value)), record.Directs?.Select(dup => new XElement("direct", new XAttribute("prop", dup.Property), new XElement("record", new XAttribute("id", dup.Value.Id))))); return(xres); }); CreateMap <RecordWithInverses, XElement>().ConvertUsing((record, context) => record == null ? null : new XElement("record", new XAttribute("id", record.Id), record.Type == null ? null : new XAttribute("type", record.Type), record.Fields?.Select(dup => new XElement("field", new XAttribute("prop", dup.Property), dup.Value)), record.Directs?.Select(dup => new XElement("direct", new XAttribute("prop", dup.Property), new XElement("record", new XAttribute("id", dup.Value.Id)))), record.Inverses?.Select(dup => new XElement("direct", new XAttribute("prop", dup.Property), new XElement("record", new XAttribute("id", dup.Value.Id)))))); // ============================== Редактирование ================================ CreateMap <Record, object>().ConvertUsing((record, context) => { int cid = store.CodeEntity(record.Id); return(new object[] { cid, Enumerable.Repeat(new object[] { cod_rdftype, store.CodeEntity(record.Type) }, 1) .Concat(record.Directs .Select(el => new object[] { store.CodeEntity(el.Property), store.CodeEntity(el.Value.Id) })).ToArray(), record.Fields .Select(el => new object[] { store.CodeEntity(el.Property), el.Value }).ToArray() }); }); CreateMap <XElement, Record>().ConvertUsing((xRecord, context) => { var xAbout = xRecord.Attribute("{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about"); if (xAbout == null) { return(null); } var props = xRecord.Elements().Select(x => (x, resource: x.Attribute("{http://www.w3.org/1999/02/22-rdf-syntax-ns#}resource"), property: "http://fogid.net/o/" + x.Name.LocalName)) .GroupBy(el => el.resource != null) .ToArray(); string id = xAbout.Value; string tp = "http://fogid.net/o/" + xRecord.Name.LocalName; return(new Record() { Id = id, Type = tp, Fields = props.Where(g => !g.Key).SelectMany(x => x) .Select(el => new RecordField { Property = el.property, Value = el.x.Value }) .ToArray(), Directs = props.Where(g => g.Key).SelectMany(x => x) .Select(el => new RecordProperty { Property = el.property, Value = new Record { Id = el.resource.Value } }).ToArray(), }); }); }
public override void LoadXFlow(IEnumerable <XElement> xflow, Dictionary <string, string> orig_ids) { IEnumerable <object> flow = xflow.Select(record => { string id = record.Attribute(ONames.rdfabout).Value; // Корректируем идентификатор if (orig_ids.TryGetValue(id, out string idd)) { id = idd; } int rec_type = store.CodeEntity(ONames.fog + record.Name.LocalName); int id_ent = store.CodeEntity(id); object[] orecord = new object[] { id_ent, (new object[] { new object[] { store.cod_rdftype, rec_type } }).Concat( record.Elements().Where(el => el.Attribute(ONames.rdfresource) != null) .Select(subel => { int prop = store.CodeEntity(subel.Name.NamespaceName + subel.Name.LocalName); string resource = subel.Attribute(ONames.rdfresource).Value; if (orig_ids.TryGetValue(resource, out string res)) { if (res != null) { resource = res; } } return(new object[] { prop, store.CodeEntity(resource) }); })).ToArray() , record.Elements().Where(el => el.Attribute(ONames.rdfresource) == null) .Select(subel => { int prop = store.CodeEntity(subel.Name.NamespaceName + subel.Name.LocalName); var xlang = subel.Attribute("{http://www.w3.org/XML/1998/namespace}lang"); string lang = xlang == null ? "" : xlang.Value; return(new object[] { prop, subel.Value, lang }); }) .ToArray() }; return(orecord); }); store.Load(flow); }