Example #1
0
        public async Task Test_Query_Index_Single()
        {
            using (var db = await OpenTestPartitionAsync())
            {
                var location = db.Root["Linq"];
                await CleanLocation(db, location);

                var indexFoos = new FdbIndex <long, string>(location.ByKey("Foos", "ByColor"));

                await db.WriteAsync(async (tr) =>
                {
                    var foos = await indexFoos.Resolve(tr);
                    foos.Add(tr, 1, "red");
                    foos.Add(tr, 2, "green");
                    foos.Add(tr, 3, "blue");
                    foos.Add(tr, 4, "red");
                }, this.Cancellation);

                // find all elements that are read
                var ids = await db.ReadAsync(async tr =>
                {
                    var lookup = indexFoos.Query(db).Lookup(x => x == "red");

                    Assert.That(lookup, Is.InstanceOf <FdbAsyncSequenceQuery <long> >());
                    Assert.That(lookup.Expression, Is.InstanceOf <FdbQueryIndexLookupExpression <long, string> >());
                    Log(lookup.Expression.GetDebugView());

                    return(await lookup.ToListAsync());
                }, this.Cancellation);

                Log("=> [ " + String.Join(", ", ids) + " ]");
            }
        }
Example #2
0
        /// <summary>Create a lookup expression on an index</summary>
        public static FdbQueryIndexLookupExpression <K, V> Lookup(FdbIndex <K, V> index, ExpressionType op, Expression value)
        {
            if (index == null)
            {
                throw new ArgumentNullException("index");
            }
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            switch (op)
            {
            case ExpressionType.Equal:
            case ExpressionType.GreaterThan:
            case ExpressionType.GreaterThanOrEqual:
            case ExpressionType.LessThan:
            case ExpressionType.LessThanOrEqual:
                break;

            default:
                throw new ArgumentException("Index lookups only support the following operators: '==', '!=', '>', '>=', '<' and '<='", "op");
            }

            //TODO: IsAssignableFrom?
            if (value.Type != typeof(V))
            {
                throw new ArgumentException("Value must have a type compatible with the index", "value");
            }

            return(new FdbQueryIndexLookupExpression <K, V>(index, op, value));
        }
        public async Task Test_Query_Index_Single()
        {
            using (var db = await OpenTestPartitionAsync())
            {
                var location = db.Partition.ByKey("Linq");

                await db.ClearRangeAsync(location, this.Cancellation);

                var index = new FdbIndex <long, string>("Foos.ByColor", location.Partition.ByKey("Foos", "ByColor"));

                await db.WriteAsync((tr) =>
                {
                    index.Add(tr, 1, "red");
                    index.Add(tr, 2, "green");
                    index.Add(tr, 3, "blue");
                    index.Add(tr, 4, "red");
                }, this.Cancellation);

                // find all elements that are read
                var lookup = index.Query(db).Lookup(x => x == "red");

                Assert.That(lookup, Is.InstanceOf <FdbAsyncSequenceQuery <long> >());
                Assert.That(lookup.Expression, Is.InstanceOf <FdbQueryIndexLookupExpression <long, string> >());
                Log(lookup.Expression.DebugView);

                var ids = await lookup.ToListAsync();

                Log("=> [ " + String.Join(", ", ids) + " ]");
            }
        }
Example #4
0
        public async Task Test_Use_Simple_Layer()
        {
            using (var db = MemoryDatabase.CreateNew("FOO"))
            {
                var location = db.GlobalSpace;

                var map   = new FdbMap <int, string>("Foos", db.GlobalSpace.Partition.ByKey("Foos"), KeyValueEncoders.Values.StringEncoder);
                var index = new FdbIndex <int, string>("Foos.ByColor", db.GlobalSpace.Partition.ByKey("Foos", "Color"));

                using (var tr = db.BeginTransaction(this.Cancellation))
                {
                    map.Set(tr, 3, @"{ ""name"": ""Juliet"", ""color"": ""red"" }");
                    map.Set(tr, 2, @"{ ""name"": ""Joey"", ""color"": ""blue"" }");
                    map.Set(tr, 1, @"{ ""name"": ""Bob"", ""color"": ""red"" }");

                    index.Add(tr, 3, "red");
                    index.Add(tr, 2, "blue");
                    index.Add(tr, 1, "red");

                    await tr.CommitAsync();
                }

                db.Debug_Dump(true);

                //// Collect memory
                //Trace.WriteLine("### GARBAGE COLLECT! ###");
                //db.Collect();
                //db.Debug_Dump();
            }
        }
Example #5
0
        /// <summary>Creates a new query on this index</summary>
        public static IFdbIndexQueryable <TId, TValue> Query <TId, TValue>(this FdbIndex <TId, TValue> index, IFdbDatabase db)
        {
            if (index == null)
            {
                throw new ArgumentNullException(nameof(index));
            }
            if (db == null)
            {
                throw new ArgumentNullException(nameof(db));
            }

            return(new FdbIndexQuery <TId, TValue>(db, index));
        }
Example #6
0
        public async Task Test_Query_Index_Range()
        {
            using (var db = await OpenTestPartitionAsync())
            {
                var location = db.Root["Linq"];
                await CleanLocation(db, location);

                var index = new FdbIndex <string, int>(location.ByKey("Foos", "ByScore"));

                await db.WriteAsync(async (tr) =>
                {
                    var foos = await index.Resolve(tr);
                    foos.Add(tr, "alpha", 10);
                    foos.Add(tr, "bravo", 16);
                    foos.Add(tr, "charly", 12);
                    foos.Add(tr, "echo", 666);
                    foos.Add(tr, "foxtrot", 54321);
                    foos.Add(tr, "golf", 768);
                    foos.Add(tr, "tango", 12345);
                    foos.Add(tr, "sierra", 667);
                    foos.Add(tr, "victor", 1234);
                    foos.Add(tr, "whisky", 9001);
                }, this.Cancellation);

                // find all up to 100
                var lookup = index.Query(db).Lookup(x => x <= 100);
                Assert.That(lookup, Is.InstanceOf <FdbAsyncSequenceQuery <string> >());
                Assert.That(lookup.Expression, Is.InstanceOf <FdbQueryIndexLookupExpression <string, int> >());
                Log(lookup.Expression.GetDebugView());

                var ids = await lookup.ToListAsync();

                Log("=> [ " + String.Join(", ", ids) + " ]");

                // find all that are over nine thousand
                lookup = index.Query(db).Lookup(x => x >= 9000);
                Assert.That(lookup, Is.InstanceOf <FdbAsyncSequenceQuery <string> >());
                Assert.That(lookup.Expression, Is.InstanceOf <FdbQueryIndexLookupExpression <string, int> >());
                Log(lookup.Expression.GetDebugView());

                ids = await lookup.ToListAsync();

                Log("=> [ " + String.Join(", ", ids) + " ]");
            }
        }
Example #7
0
        /// <summary>Create a lookup expression on an index</summary>
        /// <param name="index"></param>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static FdbQueryIndexLookupExpression <K, V> Lookup(FdbIndex <K, V> index, Expression <Func <V, bool> > expression)
        {
            if (index == null)
            {
                throw new ArgumentNullException("index");
            }

            var binary = expression.Body as BinaryExpression;

            if (binary == null)
            {
                throw new ArgumentException("Only binary expressions are allowed", "expression");
            }

            var constant = binary.Right as ConstantExpression;

            if (constant == null)
            {
                throw new ArgumentException(String.Format("Left side of expression '{0}' must be a constant of type {1}", binary.Right.ToString(), typeof(V).Name));
            }

            return(Lookup(index, binary.NodeType, constant));
        }
 internal FdbIndexQuery(IFdbDatabase db, FdbIndex <TId, TValue> index)
     : base(db)
 {
     this.Index = index;
 }
		public async Task Task_Can_Add_Update_Remove_From_Index()
		{

			using (var db = await OpenTestPartitionAsync())
			{
				var location = db.Partition("Indexing");

				// clear previous values
				await DeleteSubspace(db, location);


				var subspace = location.Partition("FoosByColor");
				var index = new FdbIndex<int, string>("Foos.ByColor", subspace);

				// add items to the index
				await db.WriteAsync((tr) =>
				{
					index.Add(tr, 1, "red");
					index.Add(tr, 2, "green");
					index.Add(tr, 3, "blue");
					index.Add(tr, 4, "green");
					index.Add(tr, 5, "yellow");
				}, this.Cancellation);

#if DEBUG
				await DumpSubspace(db, subspace);
#endif

				// lookup values

				using (var tr = db.BeginTransaction(this.Cancellation))
				{
					var reds = await index.LookupAsync(tr, "red");
					Assert.That(reds, Is.EqualTo(new int[] { 1 }));

					var greens = await index.LookupAsync(tr, "green");
					Assert.That(greens, Is.EqualTo(new int[] { 2, 4 }));

					var blues = await index.LookupAsync(tr, "blue");
					Assert.That(blues, Is.EqualTo(new int[] { 3 }));

					var yellows = await index.LookupAsync(tr, "yellow");
					Assert.That(yellows, Is.EqualTo(new int[] { 5 }));
				}

				// update

				await db.WriteAsync((tr) =>
				{
					index.Update(tr, 3, "indigo", "blue");
					index.Remove(tr, 5, "yellow");
				}, this.Cancellation);

#if DEBUG
				await DumpSubspace(db, subspace);
#endif

				// check values

				using (var tr = db.BeginTransaction(this.Cancellation))
				{
					var reds = await index.LookupAsync(tr, "red");
					Assert.That(reds, Is.EqualTo(new int[] { 1 }));

					var greens = await index.LookupAsync(tr, "green");
					Assert.That(greens, Is.EqualTo(new int[] { 2, 4 }));

					var blues = await index.LookupAsync(tr, "blue");
					Assert.That(blues.Count, Is.EqualTo(0));

					var yellows = await index.LookupAsync(tr, "yellow");
					Assert.That(yellows.Count, Is.EqualTo(0));

					var indigos = await index.LookupAsync(tr, "indigo");
					Assert.That(indigos, Is.EqualTo(new int[] { 3 }));
				}

			}

		}
		public async Task Test_Can_Combine_Indexes()
		{

			using (var db = await OpenTestPartitionAsync())
			{

				var location = await GetCleanDirectory(db, "Indexing");

				// clear previous values
				await DeleteSubspace(db, location);

				// summon our main cast
				var characters = new List<Character>()
				{
					new Character { Id = 1, Name = "Super Man", Brand="DC", HasSuperPowers = true, IsVilain = false },
					new Character { Id = 2, Name = "Batman", Brand="DC", IsVilain = false },
					new Character { Id = 3, Name = "Joker", Brand="DC", IsVilain = true },
					new Character { Id = 4, Name = "Iron Man", Brand="Marvel", IsVilain = false },
					new Character { Id = 5, Name = "Magneto", Brand="Marvel", HasSuperPowers = true, IsVilain = true },
					new Character { Id = 6, Name = "Catwoman", Brand="DC", IsVilain = default(bool?) },
				};

				var indexBrand = new FdbIndex<long, string>("Heroes.ByBrand", location.Partition("CharactersByBrand"));
				var indexSuperHero = new FdbIndex<long, bool>("Heroes.BySuper", location.Partition("SuperHeros"));
				var indexAlignment = new FdbIndex<long, bool?>("Heros.ByAlignment", location.Partition("FriendsOrFoe"));

				// index everything
				await db.WriteAsync((tr) =>
				{
					foreach (var character in characters)
					{
						indexBrand.Add(tr, character.Id, character.Brand);
						indexSuperHero.Add(tr, character.Id, character.HasSuperPowers);
						indexAlignment.Add(tr, character.Id, character.IsVilain);
					}
				}, this.Cancellation);

#if DEBUG
				await DumpSubspace(db, location);
#endif

				// super hereos only (sorry Batman!)
				using (var tr = db.BeginTransaction(this.Cancellation))
				{
					var superHeroes = await indexSuperHero.LookupAsync(tr, value: true);
					Console.WriteLine("SuperHeroes: " + string.Join(", ", superHeroes));
					Assert.That(superHeroes, Is.EqualTo(characters.Where(c => c.HasSuperPowers).Select(c => c.Id).ToList()));
				}

				// Versus !
				using (var tr = db.BeginTransaction(this.Cancellation))
				{
					var dc = await indexBrand.LookupAsync(tr, value: "DC");
					Console.WriteLine("DC: " + string.Join(", ", dc));
					Assert.That(dc, Is.EqualTo(characters.Where(c => c.Brand == "DC").Select(c => c.Id).ToList()));

					var marvel = await indexBrand.LookupAsync(tr, value: "Marvel");
					Console.WriteLine("Marvel: " + string.Join(", ", dc));
					Assert.That(marvel, Is.EqualTo(characters.Where(c => c.Brand == "Marvel").Select(c => c.Id).ToList()));
				}

				// Vilains with superpowers are the worst
				using (var tr = db.BeginTransaction(this.Cancellation))
				{
					var first = indexAlignment.Lookup(tr, value: true);
					var second = indexSuperHero.Lookup(tr, value: true);

					var merged = await first
						.Intersect(second)
						.ToListAsync();

					Assert.That(merged.Count, Is.EqualTo(1));
					Assert.That(merged[0] == characters.Single(c => c.Name == "Magneto").Id);
				}
			}

		}
		public async Task Test_Use_Simple_Layer()
		{
			using (var db = MemoryDatabase.CreateNew("FOO"))
			{
				var location = db.GlobalSpace;

				var map = new FdbMap<int, string>("Foos", db.GlobalSpace.Partition.ByKey("Foos"), KeyValueEncoders.Values.StringEncoder);
				var index = new FdbIndex<int, string>("Foos.ByColor", db.GlobalSpace.Partition.ByKey("Foos", "Color"));

				using (var tr = db.BeginTransaction(this.Cancellation))
				{
					map.Set(tr, 3, @"{ ""name"": ""Juliet"", ""color"": ""red"" }");
					map.Set(tr, 2, @"{ ""name"": ""Joey"", ""color"": ""blue"" }");
					map.Set(tr, 1, @"{ ""name"": ""Bob"", ""color"": ""red"" }");

					index.Add(tr, 3, "red");
					index.Add(tr, 2, "blue");
					index.Add(tr, 1, "red");

					await tr.CommitAsync();
				}

				db.Debug_Dump(true);

				//// Collect memory
				//Trace.WriteLine("### GARBAGE COLLECT! ###");
				//db.Collect();
				//db.Debug_Dump();
			}
		}
Example #12
0
        public async Task Task_Can_Add_Update_Remove_From_Index()
        {
            using (var db = await OpenTestPartitionAsync())
            {
                var location = db.Partition.ByKey("Indexing");

                // clear previous values
                await DeleteSubspace(db, location);


                var subspace = location.Partition.ByKey("FoosByColor");
                var index    = new FdbIndex <int, string>("Foos.ByColor", subspace);

                // add items to the index
                await db.WriteAsync((tr) =>
                {
                    index.Add(tr, 1, "red");
                    index.Add(tr, 2, "green");
                    index.Add(tr, 3, "blue");
                    index.Add(tr, 4, "green");
                    index.Add(tr, 5, "yellow");
                }, this.Cancellation);

#if DEBUG
                await DumpSubspace(db, subspace);
#endif

                // lookup values

                using (var tr = db.BeginTransaction(this.Cancellation))
                {
                    var reds = await index.LookupAsync(tr, "red");

                    Assert.That(reds, Is.EqualTo(new int[] { 1 }));

                    var greens = await index.LookupAsync(tr, "green");

                    Assert.That(greens, Is.EqualTo(new int[] { 2, 4 }));

                    var blues = await index.LookupAsync(tr, "blue");

                    Assert.That(blues, Is.EqualTo(new int[] { 3 }));

                    var yellows = await index.LookupAsync(tr, "yellow");

                    Assert.That(yellows, Is.EqualTo(new int[] { 5 }));
                }

                // update

                await db.WriteAsync((tr) =>
                {
                    index.Update(tr, 3, "indigo", "blue");
                    index.Remove(tr, 5, "yellow");
                }, this.Cancellation);

#if DEBUG
                await DumpSubspace(db, subspace);
#endif

                // check values

                using (var tr = db.BeginTransaction(this.Cancellation))
                {
                    var reds = await index.LookupAsync(tr, "red");

                    Assert.That(reds, Is.EqualTo(new int[] { 1 }));

                    var greens = await index.LookupAsync(tr, "green");

                    Assert.That(greens, Is.EqualTo(new int[] { 2, 4 }));

                    var blues = await index.LookupAsync(tr, "blue");

                    Assert.That(blues.Count, Is.Zero);

                    var yellows = await index.LookupAsync(tr, "yellow");

                    Assert.That(yellows.Count, Is.Zero);

                    var indigos = await index.LookupAsync(tr, "indigo");

                    Assert.That(indigos, Is.EqualTo(new int[] { 3 }));
                }
            }
        }
Example #13
0
        public async Task Test_Can_Combine_Indexes()
        {
            using (var db = await OpenTestPartitionAsync())
            {
                var location = await GetCleanDirectory(db, "Indexing");

                // clear previous values
                await DeleteSubspace(db, location);

                // summon our main cast
                var characters = new List <Character>()
                {
                    new Character {
                        Id = 1, Name = "Super Man", Brand = "DC", HasSuperPowers = true, IsVilain = false
                    },
                    new Character {
                        Id = 2, Name = "Batman", Brand = "DC", IsVilain = false
                    },
                    new Character {
                        Id = 3, Name = "Joker", Brand = "DC", IsVilain = true
                    },
                    new Character {
                        Id = 4, Name = "Iron Man", Brand = "Marvel", IsVilain = false
                    },
                    new Character {
                        Id = 5, Name = "Magneto", Brand = "Marvel", HasSuperPowers = true, IsVilain = true
                    },
                    new Character {
                        Id = 6, Name = "Catwoman", Brand = "DC", IsVilain = default(bool?)
                    },
                };

                var indexBrand     = new FdbIndex <long, string>("Heroes.ByBrand", location.Partition.ByKey("CharactersByBrand"));
                var indexSuperHero = new FdbIndex <long, bool>("Heroes.BySuper", location.Partition.ByKey("SuperHeros"));
                var indexAlignment = new FdbIndex <long, bool?>("Heros.ByAlignment", location.Partition.ByKey("FriendsOrFoe"));

                // index everything
                await db.WriteAsync((tr) =>
                {
                    foreach (var character in characters)
                    {
                        indexBrand.Add(tr, character.Id, character.Brand);
                        indexSuperHero.Add(tr, character.Id, character.HasSuperPowers);
                        indexAlignment.Add(tr, character.Id, character.IsVilain);
                    }
                }, this.Cancellation);

#if DEBUG
                await DumpSubspace(db, location);
#endif

                // super hereos only (sorry Batman!)
                using (var tr = db.BeginTransaction(this.Cancellation))
                {
                    var superHeroes = await indexSuperHero.LookupAsync(tr, value : true);

                    Log("SuperHeroes: " + string.Join(", ", superHeroes));
                    Assert.That(superHeroes, Is.EqualTo(characters.Where(c => c.HasSuperPowers).Select(c => c.Id).ToList()));
                }

                // Versus !
                using (var tr = db.BeginTransaction(this.Cancellation))
                {
                    var dc = await indexBrand.LookupAsync(tr, value : "DC");

                    Log("DC: " + string.Join(", ", dc));
                    Assert.That(dc, Is.EqualTo(characters.Where(c => c.Brand == "DC").Select(c => c.Id).ToList()));

                    var marvel = await indexBrand.LookupAsync(tr, value : "Marvel");

                    Log("Marvel: " + string.Join(", ", dc));
                    Assert.That(marvel, Is.EqualTo(characters.Where(c => c.Brand == "Marvel").Select(c => c.Id).ToList()));
                }

                // Vilains with superpowers are the worst
                using (var tr = db.BeginTransaction(this.Cancellation))
                {
                    var first  = indexAlignment.Lookup(tr, value: true);
                    var second = indexSuperHero.Lookup(tr, value: true);

                    var merged = await first
                                 .Intersect(second)
                                 .ToListAsync();

                    Assert.That(merged.Count, Is.EqualTo(1));
                    Assert.That(merged[0] == characters.Single(c => c.Name == "Magneto").Id);
                }
            }
        }
Example #14
0
 internal FdbQueryIndexLookupExpression(FdbIndex <K, V> index, ExpressionType op, Expression value)
     : base(Expression.Constant(index), op, value)
 {
     Contract.Requires(index != null);
     this.Index = index;
 }
		public async Task Test_Query_Index_Single()
		{
			using (var db = await OpenTestPartitionAsync())
			{

				var location = db.Partition("Linq");

				await db.ClearRangeAsync(location, this.Cancellation);

				var index = new FdbIndex<long, string>("Foos.ByColor", location.Partition("Foos", "ByColor"));

				await db.WriteAsync((tr) =>
				{
					index.Add(tr, 1, "red");
					index.Add(tr, 2, "green");
					index.Add(tr, 3, "blue");
					index.Add(tr, 4, "red");
				}, this.Cancellation);

				// find all elements that are read
				var lookup = index.Query(db).Lookup(x => x == "red");

				Assert.That(lookup, Is.InstanceOf<FdbAsyncSequenceQuery<long>>());
				Assert.That(lookup.Expression, Is.InstanceOf<FdbQueryIndexLookupExpression<long, string>>());
				Console.WriteLine(lookup.Expression.DebugView);

				var ids = await lookup.ToListAsync();
				Console.WriteLine("=> [ " + String.Join(", ", ids) + " ]");

			}

		}
		public async Task Test_Query_Index_Range()
		{
			using (var db = await OpenTestPartitionAsync())
			{

				var location = db.Partition("Linq");

				await db.ClearRangeAsync(location, this.Cancellation);

				var index = new FdbIndex<string, int>("Bars.ByScore", location.Partition("Foos", "ByScore"));

				await db.WriteAsync((tr) =>
				{
					index.Add(tr, "alpha", 10);
					index.Add(tr, "bravo", 16);
					index.Add(tr, "charly", 12);
					index.Add(tr, "echo", 666);
					index.Add(tr, "foxtrot", 54321);
					index.Add(tr, "golf", 768);
					index.Add(tr, "tango", 12345);
					index.Add(tr, "sierra", 667);
					index.Add(tr, "victor", 1234);
					index.Add(tr, "whisky", 9001);
				}, this.Cancellation);

				// find all up to 100
				var lookup = index.Query(db).Lookup(x => x <= 100);
				Assert.That(lookup, Is.InstanceOf<FdbAsyncSequenceQuery<string>>());
				Assert.That(lookup.Expression, Is.InstanceOf<FdbQueryIndexLookupExpression<string, int>>());
				Console.WriteLine(lookup.Expression.DebugView);

				var ids = await lookup.ToListAsync();
				Console.WriteLine("=> [ " + String.Join(", ", ids) + " ]");
				
				// find all that are over nine thousand
				lookup = index.Query(db).Lookup(x => x >= 9000);
				Assert.That(lookup, Is.InstanceOf<FdbAsyncSequenceQuery<string>>());
				Assert.That(lookup.Expression, Is.InstanceOf<FdbQueryIndexLookupExpression<string, int>>());
				Console.WriteLine(lookup.Expression.DebugView);

				ids = await lookup.ToListAsync();
				Console.WriteLine("=> [ " + String.Join(", ", ids) + " ]");

			}

		}