楼主: jieforest

嵌入式NoSQL数据库RaptorDB 3.1.0发布

[复制链接]
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
21#
 楼主| 发表于 2013-12-23 15:45 | 只看该作者
How the LINQ parser works in RaptorDB

In RaptorDB we want to be able to extract and query the index for each clause in the filter expression based on the order and logic of the expression. Because the indexes are built on the WAHBitArray the result will be a WAHBitArray. All this is done in the following very small code (compared to writing a language parser) :
  1.    delegate WAHBitArray QueryExpression(string colname, RDBExpression exp, object from);

  2.     internal class QueryVisitor : ExpressionVisitor
  3.     {
  4.         public QueryVisitor(QueryExpression express)
  5.         {
  6.             qexpression = express;
  7.         }
  8.         public Stack<object> _stack = new Stack<object>();
  9.         public Stack<object> _bitmap = new Stack<object>();
  10.         QueryExpression qexpression;

  11.         protected override Expression VisitBinary(BinaryExpression b)
  12.         {
  13.             this.Visit(b.Left);
  14.             ExpressionType t = b.NodeType;

  15.             if (t == ExpressionType.Equal || t == ExpressionType.LessThan || t == ExpressionType.LessThanOrEqual ||
  16.                 t == ExpressionType.GreaterThan || t == ExpressionType.GreaterThanOrEqual)
  17.                 _stack.Push(b.NodeType);
  18.            
  19.             this.Visit(b.Right);
  20.             t = b.NodeType;
  21.             if (t == ExpressionType.Equal || t == ExpressionType.NotEqual ||
  22.                 t == ExpressionType.LessThanOrEqual || t == ExpressionType.LessThan ||
  23.                 t == ExpressionType.GreaterThanOrEqual || t == ExpressionType.GreaterThan)
  24.             {
  25.                 // binary expression
  26.                 object lv = _stack.Pop();
  27.                 ExpressionType lo = (ExpressionType)_stack.Pop();
  28.                 object ln = _stack.Pop();
  29.                 RDBExpression exp = RDBExpression.Equal;
  30.                
  31.                 if (lo == ExpressionType.LessThan)
  32.                     exp = RDBExpression.Less;
  33.                 else if (lo == ExpressionType.LessThanOrEqual)
  34.                     exp = RDBExpression.LessEqual;
  35.                 else if (lo == ExpressionType.GreaterThan)
  36.                     exp = RDBExpression.Greater;
  37.                 else if (lo == ExpressionType.GreaterThanOrEqual)
  38.                     exp = RDBExpression.GreaterEqual;

  39.                 _bitmap.Push(qexpression("" + ln, exp, lv));
  40.             }

  41.             if (t == ExpressionType.And || t == ExpressionType.AndAlso ||
  42.                 t == ExpressionType.Or || t == ExpressionType.OrElse)
  43.             {
  44.                 // do bitmap operations
  45.                 WAHBitArray r = (WAHBitArray)_bitmap.Pop();
  46.                 WAHBitArray l = (WAHBitArray)_bitmap.Pop();

  47.                 if (t == ExpressionType.And || t == ExpressionType.AndAlso)
  48.                     _bitmap.Push(r.And(l));
  49.                 if (t == ExpressionType.Or || t == ExpressionType.OrElse)
  50.                     _bitmap.Push(r.Or(l));
  51.             }
  52.             return b;
  53.         }

  54.         protected override Expression VisitMethodCall(MethodCallExpression m)
  55.         {
  56.             string s = m.ToString();
  57.             _stack.Push(s.Substring(s.IndexOf('.') + 1));
  58.             return m;
  59.         }

  60.         protected override Expression VisitMember(MemberExpression m)
  61.         {
  62.             var e = base.VisitMember(m);
  63.             var c = m.Expression as ConstantExpression;
  64.             if (c != null)
  65.             {
  66.                 Type t = c.Value.GetType();
  67.                 var x = t.InvokeMember(m.Member.Name, BindingFlags.GetField, null, c.Value, null);
  68.                 _stack.Push(x);
  69.             }
  70.             if (m.Expression != null && m.Expression.NodeType == ExpressionType.Parameter)
  71.             {
  72.                 _stack.Push(m.Member.Name);
  73.                 return e;
  74.             }
  75.             return e;
  76.         }

  77.         protected override Expression VisitConstant(ConstantExpression c)
  78.         {
  79.             IQueryable q = c.Value as IQueryable;
  80.             if (q != null)
  81.                 _stack.Push(q.ElementType.Name);
  82.             else if (c.Value == null)
  83.                 _stack.Push(null);
  84.             else
  85.             {
  86.                 _stack.Push(c.Value);
  87.                 if (Type.GetTypeCode(c.Value.GetType()) == TypeCode.Object)
  88.                     _stack.Pop();
  89.             }
  90.             return c;
  91.         }
  92.     }
复制代码

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
22#
 楼主| 发表于 2013-12-24 14:52 | 只看该作者
Most of the work is done in the VisitBinary method (for evaluating logical [&& || ] operations and clauses [b>3] ) so to distinguish the two a stack is used store the clause values for further processing. VisitBinary will be called recursively for left and right sides of expressions so a stack of bitmap is also required for aggregating the results of the expression.

The constructor to the class takes two delegates which are supplied by the caller for handles to the underlying indexes which this class calls when a binary clause is completely parsed. The results are push onto the bitmap stack.

The VisitMember method is responsible for replacing the compiler generated code for constant values with the appropriate value ( the j in the above example).

The rest of the code is generally for extracting the "column names" without the prefixes (s.Serial -> Serial etc.).

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
23#
 楼主| 发表于 2013-12-24 14:52 | 只看该作者
A sample application

To work with RaptorDB all you need to do is follow these steps :

1)Define your Entities (plain c# objects) as you would doing domain driven development.

2)Create a Primary View for your base Entities.

3)Register your views with RaptorDB.

4)Save and query your data.

5)Add new views based on your requirements.

As you will see below this is so easy and simple that it just happens and you don't need to learn anything new or worry about configurations or breaking things at runtime as the compiler will catch your error at compile time.

A great feature is the total absence of anything SQL related, the associated schema pains and having to switch to a database management product to define and check tables and columns as everything is in your source file.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
24#
 楼主| 发表于 2013-12-24 14:53 | 只看该作者
1. Creating Entities

The first thing you should do is define your entities or data classes (referred to as domain driven development), these are plain c# (vb.net) classes or POCO's like the following :.
  1. public class LineItem
  2.     {
  3.         public decimal QTY { get; set; }
  4.         public string Product { get; set; }
  5.         public decimal Price { get; set; }
  6.         public decimal Discount { get; set; }
  7.     }

  8.     public class SalesInvoice
  9.     {
  10.         public SalesInvoice()
  11.         {
  12.             ID = Guid.NewGuid();
  13.         }
  14.         public Guid ID { get; set; }
  15.         public string CustomerName { get; set; }
  16.         public string Address { get; set; }
  17.         public List<LineItem> Items { get; set; }
  18.         public DateTime Date { get; set; }
  19.         public int Serial { get; set; }
  20.         public byte Status { get; set; }
  21.     }
复制代码
There is nothing special about the above other than the lack of anything extra you need to do like adding attributes etc. (even Serializable) as they are not needed.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
25#
 楼主| 发表于 2013-12-24 14:53 | 只看该作者
2. Creating Views

Next you create your primary view for your entities as follows :
  1.    public class SalesInvoiceView : View<SalesInvoice> // create a view for the SalesInvoice type
  2.     {
  3.         public class RowSchema  // define the schema for this view
  4.         {
  5.             public NormalString CustomerName; // CustomerName is a normal string index
  6.             public DateTime InvoiceDate;
  7.             public string Address;
  8.             public int Serial;
  9.             public byte Status;
  10.         }

  11.         public SalesInvoiceView()
  12.         {
  13.             this.Name = "SalesInvoice";
  14.             this.Description = "A primary view for SalesInvoices";
  15.             this.isPrimaryList = true;
  16.             this.isActive = true;
  17.             this.BackgroundIndexing = true;

  18.             this.Schema = typeof(SalesInvoiceView.RowSchema);

  19.             this.AddFireOnTypes(typeof(SalesInvoice));

  20.             this.Mapper = (api, docid, doc) =>
  21.             {
  22.                 api.Emit(docid, doc.CustomerName, doc.Date, doc.Address, doc.Serial, doc.Status);
  23.             };
  24.         }
  25.     }
复制代码

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
26#
 楼主| 发表于 2013-12-24 14:54 | 只看该作者
This is pretty straight forward also.

1)This view is for a SalesInvoice object type.

2)RowSchema is a class which defines the columns for this view
You can name this class anything as long as you register it with the Schema property
All value types are supported (int, string, decimal etc.)
NormalString is a special type which instructs the indexer to index this column as a string so you will have to specify all the string when querying.
If you specify a string property then RaptorDB will do full text indexing on that column, so you can search for words within that column when querying.

3)BackgroundIndexing controls how the indexer does it's work on this view (i.e. block saves until each document is indexed when false).

4)AddFireOnTypes controls when this view is called based on the input document type

5)Mapper is the map function which will populate this view (i.e. extract information from the input document), you can add logic here if you need it. The order of the items must be the same as the schema you defined.

6)With api you can Fetch a document, log debug information and Query another view.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
27#
 楼主| 发表于 2013-12-25 11:32 | 只看该作者
3. Registering Views

Registering a view is as simple as :
  1. if (rap.RegisterView(new SalesInvoiceView()).OK == false)
  2.         {
  3.                 Console.WriteLine("Error registering view");
  4.                 return;
  5.         }
复制代码
RaptorDB will do some checks on your view and if everything is fine it will return true, which means you are good to go.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
28#
 楼主| 发表于 2013-12-25 11:32 | 只看该作者
4. Saving and querying data

Now you can use RaptorDB and save documents as follows :
  1. var inv = new SalesInvoice()
  2.    {
  3.        Date = FastDateTime.Now,
  4.        Serial = i % 10000,
  5.        CustomerName = "me " + i % 10,
  6.        Status = (byte)(i % 4),
  7.        Address = "df asd sdf asdf asdf"
  8.    };
  9.    inv.Items = new List<LineItem>();
  10.    for (int k = 0; k < 5; k++)
  11.        inv.Items.Add(new LineItem()
  12.             { Product = "prod " + k, Discount = 0, Price = 10 + k, QTY = 1 + k });

  13.    rap.Save(inv.ID, inv); // save to RaptorDB
复制代码

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
29#
 楼主| 发表于 2013-12-25 11:33 | 只看该作者
Querying is as simple as writing LINQ predicates like the following:
  1. var q = rap.Query(typeof(SalesInvoice), // call by the view type or the primary document type
  2.                 (SalesInvoice s) => (s.Serial < j) && (s.Status == 1 || s.Status == 3));

  3. q = rap.Query("SalesItemRows",  // call by the view name
  4.         (LineItem l) => (l.Product == "prod 1" || l.Product == "prod 3"));
复制代码
As you can see you can call the query in 2 ways by specifying the type of the view (or type of the document type for primary views) or by calling the string name of the view.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
30#
 楼主| 发表于 2013-12-25 11:33 | 只看该作者
Screen Shots

From the below image you can see the test application doing its work. RaptorDB was configured to do background indexing, so 100,000 documents were inserted in 12 secs and the primary view was populated (the query results for 500 items) and the background indexer is working on populating the other view defined, which after a couple of queries shows the final results of 50,000 items.

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表