// =========================== Основные выборки и поиски =============================== public override XElement GetItemByIdBasic(string id, bool addinverse) { int cid = store.CodeEntity(id); object[] tri = (object[])store.GetRecord(cid); if (tri == null) { return(null); } object[] pair = ((object[])tri[1]).Cast <object[]>().FirstOrDefault(dup => (int)dup[0] == store.cod_rdftype); XElement xres = new XElement("record", new XAttribute("id", id), pair == null?null: new XAttribute("type", store.DecodeEntity((int)pair[1])), ((object[])tri[2]).Cast <object[]>().Select(dup => { return(new XElement("field", new XAttribute("prop", store.DecodeEntity((int)dup[0])), ((string)dup[2] == ""?null: new XAttribute("{http://www.w3.org/XML/1998/namespace}lang", (string)dup[2])), (string)dup[1])); }), ((object[])tri[1]).Cast <object[]>().Where(dup => (int)dup[0] != store.cod_rdftype).Select(dup => { return(new XElement("direct", new XAttribute("prop", store.DecodeEntity((int)dup[0])), new XElement("record", new XAttribute("id", store.DecodeEntity((int)dup[1]))))); }), null); if (addinverse) { var inv = store.GetRefers(cid); xres.Add(inv.Cast <object[]>().Select(tr => { int c = (int)tr[0]; object[] found = ((object[])tr[1]).Cast <object[]>().FirstOrDefault(dup => (int)dup[1] == cid); return(new XElement("inverse", new XAttribute("prop", store.DecodeEntity((int)found[0])), new XElement("record", new XAttribute("id", store.DecodeEntity(c))))); })); } return(xres); }
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 static void Main20() { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); System.Random rnd = new Random(); //string path = "../../../../data/Databases/"; string path = "C:/Home/data/Databases/"; int fnom = 0; Func <Stream> GenStream = () => File.Open(path + (fnom++), FileMode.OpenOrCreate); Console.WriteLine("Start TestConsoleApp (Main32)"); TripleRecordStore store = new TripleRecordStore(GenStream, path, new string[] { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" , "http://fogid.net/o/name" , "http://fogid.net/o/age" , "http://fogid.net/o/person" , "http://fogid.net/o/photo-doc" , "http://fogid.net/o/reflection" , "http://fogid.net/o/reflected" , "http://fogid.net/o/in-doc" }); int npersons = 40_000; int nphotos = npersons * 2; int nreflections = npersons * 6; bool toload = true; bool tocode = true; if (toload) { sw.Restart(); store.Clear(); var persons = Enumerable.Range(0, npersons).Select(i => npersons - i - 1) .Select(c => new object[] { -c - 1, // Это "прямой" код не требующий кодирования через таблицу new object[] { new object[] { 0, 3 } }, new object[] { new object[] { 1, "p" + c }, new object[] { 2, "" + 33 } } }); var persons2 = Enumerable.Range(0, npersons).Select(i => npersons - i - 1) .Select(c => store.CodeRecord(new object[] { "" + c, new object[] { new object[] { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", "http://fogid.net/o/person" } }, new object[] { new object[] { "http://fogid.net/o/name", "p" + c }, new object[] { "http://fogid.net/o/age", "" + 33 } } })); var persons3 = Enumerable.Range(0, npersons).Select(i => npersons - i - 1) .Select(c => store.CodeRecord(new object[] { "" + c, // Это "прямой" код не требующий кодирования через таблицу new object[] { new object[] { 0, 3 } }, new object[] { new object[] { 1, "p" + c }, new object[] { 2, "" + 33 } } })); var photos = Enumerable.Range(0, nphotos).Select(i => nphotos - i - 1) .Select(c => new object[] { -(c + npersons) - 1, // Это "прямой" код не требующий кодирования через таблицу new object[] { new object[] { 0, 4 } }, new object[] { new object[] { 1, "f" + c } } }); var photos2 = Enumerable.Range(0, nphotos).Select(i => nphotos - i - 1) .Select(c => store.CodeRecord(new object[] { "" + (c + npersons), new object[] { new object[] { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", "http://fogid.net/o/photo-doc" } }, new object[] { new object[] { "http://fogid.net/o/name", "f" + c } } })); var photos3 = Enumerable.Range(0, nphotos).Select(i => nphotos - i - 1) .Select(c => store.CodeRecord(new object[] { "" + (c + npersons), // Это "прямой" код не требующий кодирования через таблицу new object[] { new object[] { 0, 4 } }, new object[] { new object[] { 1, "f" + c } } })); var reflections = Enumerable.Range(0, nreflections).Select(i => nreflections - i - 1) .Select(c => new object[] { -(c + 3 * npersons) - 1, // Это "прямой" код не требующий кодирования через таблицу new object[] { new object[] { 0, 5 }, new object[] { 6, -1 - (rnd.Next(npersons)) }, new object[] { 7, -1 - (rnd.Next(nphotos) + npersons) } }, new object[] { } }); var reflections2 = Enumerable.Range(0, nreflections).Select(i => nreflections - i - 1) .Select(c => store.CodeRecord(new object[] { "" + (c + 3 * npersons), new object[] { new object[] { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", "http://fogid.net/o/reflection" }, new object[] { "http://fogid.net/o/reflected", "" + rnd.Next(npersons) }, new object[] { "http://fogid.net/o/in-doc", "" + (rnd.Next(nphotos) + npersons) } }, new object[] { } })); var reflections3 = Enumerable.Range(0, nreflections).Select(i => nreflections - i - 1) .Select(c => store.CodeRecord(new object[] { "" + (c + 3 * npersons), // Это "прямой" код не требующий кодирования через таблицу new object[] { new object[] { 0, 5 }, new object[] { 6, "" + rnd.Next(npersons) }, new object[] { 7, "" + (rnd.Next(nphotos) + npersons) } }, new object[] { } })); if (tocode) { store.Load(persons2.Concat(photos2).Concat(reflections2)); //store.Load(persons3.Concat(photos3).Concat(reflections3)); } else { store.Load(persons.Concat(photos).Concat(reflections)); } store.Build(); sw.Stop(); Console.WriteLine($"Load ok. duration={sw.ElapsedMilliseconds}"); } //else { sw.Restart(); store.Refresh(); sw.Stop(); Console.WriteLine($"Refresh for Phototeka {npersons} persons. Duration={sw.ElapsedMilliseconds}"); } // ПОлукодирование иногда кодирование, иногда нет Func <int, int> HCode = nom => tocode?store.Code("" + nom) : -1 - nom; // Проверка int code = HCode(npersons * 2 / 3); var query1 = store.GetRecord(code); Console.WriteLine(store.ToTT(query1)); // Скорость выполнения запросов int nprobe = 10000; sw.Restart(); for (int i = 0; i < nprobe; i++) { int c = HCode(rnd.Next(npersons)); var ob = store.GetRecord(c); } sw.Stop(); Console.WriteLine($"{nprobe} GetRecord() ok. duration={sw.ElapsedMilliseconds}"); // Надо найти все фотографии, в которых отражается персона с выбранным (случайно) кодом. sw.Restart(); int total = 0; nprobe = 1000; for (int i = 0; i < nprobe; i++) { int c = HCode(rnd.Next(npersons)); var query2 = store.GetRefers(c).Cast <object[]>().ToArray(); var q3 = query2 .Select(ob => ((object[])ob[1]).Cast <object[]>() .First(dupl => (int)dupl[0] == 7)); var q4 = q3 .Select(bb => store.GetRecord((int)bb[1])).ToArray(); total += query2.Count(); } sw.Stop(); Console.WriteLine($"{nprobe} persons for photos ok. duration={sw.ElapsedMilliseconds} total={total}"); //var likes = store.Like("p" + 666); //foreach (var like in likes) //{ // Console.WriteLine($"like {store.ToTT(like)}"); //} sw.Restart(); total = 0; for (int i = 0; i < 1000; i++) { string id = "p" + rnd.Next(npersons / 10 + 1, npersons); total += store.Like(id).Count(); } sw.Stop(); Console.WriteLine($"{nprobe} likes for persons ok. duration={sw.ElapsedMilliseconds} total={total}"); }