使用mongodb实现多选

作者: 太白菜Rennbon | 来源:发表于2018-03-06 22:58 被阅读16次

本文主要目的,解决多选项数据存储问题,如选择了A和B 2个选项,数据该怎么存

经过

对于很多办公协作软件,多选的数据存储格式对于后期的拓展尤为重要。
去年,因为公司的业务需求,开发了一套自定义控件,包括文本,单选多选,公式,附件等控件一共20多种。但是因为天真选择类控件用了10进制来存储,用了2的n次幂这种方式,选择的存储介质是Mongodb,因为Mongodb的$bitsAnySet对于筛选的支持尤为的强大。

然而上线后,因为客户的使用会涉及大量的选项录入,倒置double类型10进制精度的丢失,八阿哥真是拦都拦不住,也因为工期紧,一直都没去想补偿方案填补这个漏洞。近期因为新模块对控件的使用,填补这个漏洞又搬上了议程,经过大神的指点以及自己的摸索,已经完成了替换的方案,设计方式如下:

  1. 后端数据库mongodb存binary 下 bindata(0,"")二进制格式
  2. 前端暴露为二进制字符串,如 "101010101"

具体mongo查询逻辑

https://docs.mongodb.com/manual/reference/operator/query/bitsAnySet/

C#=>mongodb bindata格式

https://jira.mongodb.org/browse/CSHARP-437

下面为C#实现的各个进制互转等帮助类方法


        /// <summary>
        /// 二进制字符串转byte[]
        /// </summary>
        /// <param name="binaryStr"></param>
        /// <returns></returns>
        public static byte[] ConvertBinaryStringToBytes(string binaryStr)
        {
            binaryStr = binaryStr.Replace("-", string.Empty);
            binaryStr = BinaryLengthAppendTo8(binaryStr);
            byte[] resultantArray = new byte[binaryStr.Length / 8];
            for (int i = 0; i < resultantArray.Length; i++)
            {
                var str = binaryStr.Substring(i * 8, 8);
                resultantArray[i] = Convert.ToByte(str, 2);
            }
            return resultantArray;
        }


        /// <summary>
        /// 二进制字符串转base64
        /// </summary>
        /// <param name="binaryStr"></param>
        /// <returns></returns>
        public static string ConvertBinaryStringToBase64(string binaryStr)
        {
            var byteArr = ConvertBinaryStringToByteArr(binaryStr);
            return Convert.ToBase64String(byteArr);
        }
        /// <summary>
        /// 10进制转二进制字符串("100010010"格式)
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public static string ConvertDoubleToString(double num)
        {
            List<string> binary = new List<string>();
            while (num > 0)
            {
                double tmp = num;
                num = Math.Floor(tmp / 2);
                binary.Add((tmp % 2).ToString());
            }
            binary.Reverse();
            return string.Join(string.Empty, binary);
        }
        /// <summary>
        /// btye[]转二进制字符串
        /// </summary>
        /// <param name="bindata"></param>
        /// <returns></returns>
        public static string ConvertBinaryToString(byte[] bindata)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < bindata.Length; i++)
            {
                string hv = Convert.ToString(bindata[i], 2);
                hv = BinaryLengthAppendTo8(hv);
                sb.Append(hv);
            }
            return sb.ToString();
        }
        public static byte[] ConvertDoubleToBytes(double num)
        {
            return ConvertBinaryStringToByteArr(ConvertDoubleToString(num));
        }
        /// <summary>
        /// 转换bindata到十进制double(强转溢出后返回-1)
        /// </summary>
        /// <param name="bindata"></param>
        /// <returns></returns>
        public static double ConvertBinaryToDouble(byte[] bindata)
        {

            string binary = ConvertBinaryToString(bindata);
            return ConvertBinaryStrToDouble(binary);

        }
        /// <summary>
        /// 转换"10101010"到十进制double(强转溢出后返回-1)
        /// </summary>
        /// <param name="binaryStr"></param>
        /// <returns></returns>
        public static double ConvertBinaryStrToDouble(string binaryStr)
        {
            try
            {
                int binLen = binaryStr.Length;
                double sum = 0;
                for (int i = 0; i < binLen; i++)
                {
                    if (binaryStr[i] == '1')
                    {
                        sum += Math.Pow(2, binLen - i - 1);
                    }
                }
                if (double.IsInfinity(sum))
                {
                    throw new Exception("溢出");
                }
                return sum;
            }
            catch
            {
                return -1;
            }

        }
        private static string BinaryLengthAppendTo8(string binaryStr)
        {
            int m = binaryStr.Length % 8;
            if (m != 0)
            {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < 8 - m; i++)
                {
                    sb.Append("0");
                }
                binaryStr = sb.ToString() + binaryStr;
            }
            return binaryStr;
        }


相关文章

网友评论

    本文标题:使用mongodb实现多选

    本文链接:https://www.haomeiwen.com/subject/tbcdfftx.html