哈哈勋爵 發表於 2019-8-20 16:12:00

谨慎 mongodb 关于数字操作可能导致类型及精度变化

<h3>1.问题描述</h3>
<p>最近有一个需求,更新Mongo数据库中 原料 集合的某字段价格,更新后,程序报错了,说长度过长了,需要Truncation。</p>
<p>主要错误信息如下:</p>
<div class="cnblogs_code">
<pre>FormatException: An error occurred <span style="color: rgba(0, 0, 255, 1)">while</span> deserializing the XXXXXXXPrice property of class XXXXXXXXXXXXXXXXXXXX: Truncation resulted <span style="color: rgba(0, 0, 255, 1)">in</span> data loss.</pre>
</div>
<p>&nbsp;</p>
<p>调试发现,价格这个数据来自于SQL Server数据库,是<span class="ask-title">decimal(18,4),数据落到Mongodb中也是Decimal类型。DBA通过Mongodb客户端工具更新后,更新的文档中的价格字段由Decimal类型变成了Double类型。</span></p>
<p>此时问题就出现了:</p>
<p>(1):Double类型为15位,原来小数点后面是四位小数,现在不一定了。</p>
<p>(2):精确度变化,导致部分数据失真。</p>
<p>问题出现,我们有必要认认真真学习总结下MongoDB中的数字类型以及其余mongo shell等常见客户端工具。</p>
<p>在MongoDB中,关于数值的类型有:</p>
<table border="0">
<tbody>
<tr>
<td><span style="font-size: 16px"><strong>Type</strong></span></td>
<td><span style="font-size: 16px"><strong>Alias</strong></span></td>
<td><span style="font-size: 16px"><strong>Notes</strong></span></td>
</tr>
<tr>
<td>Double</td>
<td>“double”</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>32-bit integer</td>
<td>“int”</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>64-bit integer</td>
<td>“long”</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Decimal128</td>
<td>“decimal”</td>
<td>New in version 3.4</td>
</tr>
</tbody>
</table>
<h3>2. 数字默认为double 类型</h3>
<p>mongo shell 客户端默认将数字看成浮点数。</p>
<p>例如,</p>
<div class="cnblogs_code">
<pre>db.testnumber.<span style="color: rgba(0, 0, 255, 1)">find</span>({t1:<span style="color: rgba(128, 0, 128, 1)">12345</span>})</pre>
</div>
<p>查看新插入的数据,</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819102126985-577915788.png"></p>
<p>可以看到,<strong>数字变成了<span style="color: rgba(255, 0, 0, 1)">Double 类型</span>。</strong></p>
<p>上面的数据插入是在mongo shell 中 验证的,其实<strong>在&nbsp;nosqlbooster 工具 中,默认也是将数字当成double类型。</strong></p>
<h3>3 NumberLong 类型</h3>
<p>如果想保留为int类型(64-bit integer),需要显式地通过<strong>封装函数<span style="color: rgba(255, 0, 0, 1)">NumberLong()</span></strong>,其接受的参数应为string类型。</p>
<p>例如,插入一笔数据</p>
<div class="cnblogs_code">
<pre>db.testnumber.insertOne( { _id: <span style="color: rgba(128, 0, 128, 1)">10</span>, calc: NumberLong(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">2090845886852</span><span style="color: rgba(128, 0, 0, 1)">"</span>) } )</pre>
</div>
<p>&nbsp;查看插入的数据</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819103349192-1475518516.png"></p>
<p>mongo shell 客户端查询,显式如下:</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819103645492-1093082991.png"></p>
<p>我们再来验证下通过mongo shell 工具如何对这一类型进行更新的:</p>
<div class="cnblogs_code">
<pre>db.collection.updateOne( { _id: <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)"> },
                      { $set:{ calc: NumberLong(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">25555550</span><span style="color: rgba(128, 0, 0, 1)">"</span>) } } )</pre>
</div>
<p>显式指定&nbsp;<strong>封装函数NumberLong()</strong>。</p>
<p>查看更新后的数据,</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819103850572-819783510.png"></p>
<p>我们再来验证下 long&nbsp; 类型上的<strong>&nbsp;</strong><span class="nx"><strong>$inc 操作</strong>($inc操作符将一个字段的值增加或者减少指定的数值)</span></p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>db.testnumber.updateOne( { _id: <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)"> },
...                     { $inc: { calc: NumberLong(</span><span style="color: rgba(128, 0, 128, 1)">5</span>) } } )</pre>
</div>
<p>更新后,查询</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819105146587-834542023.png"></p>
<p>上面的例子中,显式地指定了Int64 类型(通过NumberLong()函数),执行前后都是Int64。如果不指定呢?不指定就是默认的Double类型。</p>
<p>继续测试,在原来的基础上再加5.</p>
<div class="cnblogs_code">
<pre>db.testnumber.updateOne( { _id: <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)"> },
...                     { $inc: { calc: </span><span style="color: rgba(128, 0, 128, 1)">5</span> } } )</pre>
</div>
<p>查看显示,</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819105656749-1888561413.png"></p>
<p><strong>数值的类型由Int64 变成了 Double 类型。</strong></p>
<h3>4.32-bit integer (int) 类型</h3>
<p>和64-bit integer(long)差不多,不同的是,其转换函数由NumberLong()变成了<strong><span style="color: rgba(255, 0, 0, 1)">&nbsp;<code class="docutils literal"><span class="pre">NumberInt()</span></code>&nbsp;</span></strong>,其接受的参数,也当成string类型来处理。</p>
<p>例如:</p>
<div class="cnblogs_code">
<pre>db.testnumber.insert({ts:<strong>NumberInt</strong>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">246</span><span style="color: rgba(128, 0, 0, 1)">"</span>)})</pre>
</div>
<p>查看插入的数据:</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819113128490-896046689.png"></p>
<p>数据类型为Int32.</p>
<h3>5.NumberDecimal</h3>
<p>Decimal 这个数据类型是在Mongo 3.4 才开始引入的。新增Decimal数值类型主要是为了记录、处理货币数据&nbsp;,例如 财经数据、税率数据等。有时候,一些科学计算也采用Decimal类型。</p>
<p>因为mongo shell默认将数字当成double类型,所以也是需要显式的<strong><span style="color: rgba(255, 0, 0, 1)">转换函数NumberDecimal()</span></strong>,其接受参数是string值。</p>
<p>例如:</p>
<div class="cnblogs_code">
<pre>db.testnumber.insert({ts:NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1000.55</span><span style="color: rgba(128, 0, 0, 1)">"</span>)})</pre>
</div>
<p>查询显示:</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819134348573-551662418.png"></p>
<p>我们前面,强调说,<strong><span style="color: rgba(255, 0, 0, 1)">参数接受类型是string</span></strong>,<strong>如何是数字(默认是double类型)也可以,但是有精度丢失的风险,会把数字变成15位(小数点不计算在内)。</strong></p>
<p>例如</p>
<div class="cnblogs_code">
<pre> db.testnumber.insert({ts:NumberDecimal(<span style="color: rgba(128, 0, 128, 1)">1000.88</span>)})</pre>
</div>
<p>查看</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : ObjectId(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">5d5a38fa3e8964310aa46f83</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1000.88000000000</span><span style="color: rgba(128, 0, 0, 1)">"</span>) }</pre>
</div>
<p>再插入一笔</p>
<div class="cnblogs_code">
<pre>db.testnumber.insert({ts:NumberDecimal(<span style="color: rgba(128, 0, 128, 1)">1000000000.88</span>)})</pre>
</div>
<p>查询这一笔数据</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : ObjectId(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">5d5a39103e8964310aa46f84</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1000000000.88000</span><span style="color: rgba(128, 0, 0, 1)">"</span>) }</pre>
</div>
<p>再插入一笔</p>
<div class="cnblogs_code">
<pre>db.testnumber.insert({ts:NumberDecimal(<span style="color: rgba(128, 0, 128, 1)">10000000000000.88</span>)})</pre>
</div>
<p>查询变成了</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : ObjectId(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">5d5a3e343e8964310aa46f86</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10000000000000.9</span><span style="color: rgba(128, 0, 0, 1)">"</span>) }</pre>
</div>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819142838267-762560922.png"></p>
<p>再如</p>
<p>&nbsp;<img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819142919570-396096652.png"></p>
<p>需要注意的是:如果将数字类型数据作为参数传递给NumberDecimal(),只能出现在mongo shell工具中,在其他工具中可能报错。</p>
<p>例如在工具&nbsp;nosqlbooster&nbsp;中就报错。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">message</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">NumberDecimal param must be string.</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">stack</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">script:1:29</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p>&nbsp;测试案例如下:</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819143430547-1795832770.png"></p>
<h3>6.mongo shell 操作Decima类型</h3>
<p>如果在mongo shell 操作Decimal,需特别小心,其数据类型和精度有可能变化。</p>
<p><strong>Case 1&nbsp;</strong></p>
<p>Decimal 类型 +&nbsp;&nbsp;&nbsp;Decimal 类型</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819145904092-2078415332.png"></p>
<p><strong>Case 2</strong></p>
<p>Decimal 类型 + long 类型</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819150832732-1961417310.png"></p>
<p><strong>Case 3</strong></p>
<p>Decimal 类型+ Int 类型</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819151955980-1834031369.png"></p>
<p><strong>Case 4</strong></p>
<p>Decimal 类型 + 数值 类型,即加数是默认的Double类型</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819152722652-1599413707.png"></p>
<p><strong>Case 5</strong></p>
<p>如果将两个Decimal字段相减,会是什么样子呢?我们先在mongo shell 段进行测试。</p>
<p>测试数据:</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : ObjectId(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">5d5a50ebbd9dcf1c9b374e11</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts1</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">32222.21111</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts2</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">11222.21111</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tst</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">2211.11111</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">) }
{ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : ObjectId(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">5d5a50f5bd9dcf1c9b374e12</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts1</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">22222.21111</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts2</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">22222.21111</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tst</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">11111.11111</span><span style="color: rgba(128, 0, 0, 1)">"</span>) }</pre>
</div>
<p>相减操作,将tst字段设置为ts1 和 ts2的差值。</p>
<div class="cnblogs_code">
<pre> db.testnumber.<span style="color: rgba(0, 0, 255, 1)">find</span>({}).forEach(<span style="color: rgba(0, 0, 255, 1)">function</span>(item){   item.tst = item.ts1- item.ts2 ;db.testnumber.save(item) })</pre>
</div>
<p>查询相减后的结果:</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : ObjectId(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">5d5a50ebbd9dcf1c9b374e11</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts1</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">32222.21111</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts2</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">11222.21111</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tst</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> : NaN }
{ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : ObjectId(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">5d5a50f5bd9dcf1c9b374e12</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts1</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">22222.21111</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts2</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">22222.21111</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tst</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NaN }</pre>
</div>
<p>此时出现了<strong><span style="color: rgba(255, 0, 0, 1)">NAN类型。</span></strong></p>
<p><code>NaN</code>&nbsp;(not a number)属性代表一个“不是数字”的值。这个特殊的值是因为运算不能执行而导致的,不能执行的原因要么是因为其中的运算对象之一非数字(例如,&nbsp;<code>"abc" / 4</code>),要么是因为运算的结果非数字(例如,除数为零)。</p>
<p>虽然&nbsp;<code>NaN</code>&nbsp;意味着“不是数字”,但是它的类型是&nbsp;<code>Number</code></p>
<p><strong>Case 6</strong></p>
<p>相加(+)操作,在mongo shell 中验证:</p>
<div class="cnblogs_code">
<pre>db.testnumber.<span style="color: rgba(0, 0, 255, 1)">find</span>({}).forEach(<span style="color: rgba(0, 0, 255, 1)">function</span>(item){   item.tst = item.ts1+ item.ts2 ;db.testnumber.save(item) })</pre>
</div>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819170543662-1143607014.png"></p>
<p>此时类似string拼凑。</p>
<p><strong>Case 7&nbsp;</strong></p>
<p>相减操作如果发生在其他客户端工具,例如&nbsp;nosqlbooster 工具,效果怎么样呢?</p>
<p>执行相减命令</p>
<div class="cnblogs_code">
<pre> db.testnumber.<span style="color: rgba(0, 0, 255, 1)">find</span>({}).forEach(<span style="color: rgba(0, 0, 255, 1)">function</span>(item){   item.tst = item.ts1- item.ts2 ;db.testnumber.save(item) })</pre>
</div>
<p>结果截图</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819171014487-159203491.png"></p>
<p><strong>可知:在客户端工具&nbsp;nosqlbooster 中,两个Decimal类型数据的差值是Double类型。</strong></p>
<p><strong>Case 8&nbsp;</strong></p>
<p>在工具nosqlbooster 上执行相加的命令</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">db.testnumber.</span><span style="color: rgba(0, 0, 255, 1)">find</span>({}).forEach(<span style="color: rgba(0, 0, 255, 1)">function</span>(item){   item.tst = item.ts1+ item.ts2 ;db.testnumber.save(item) })</pre>
</div>
<p>查询结果</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819171304042-439684823.png"></p>
<p><strong>在客户端工具&nbsp;nosqlbooster 中,两个Decimal类型数据的 和 也是Double类型。</strong></p>
<p>Case 7、Case 8表明 在 <strong>客户端工具&nbsp;nosqlbooster 中 ,加减两个</strong>decimal类型数据,其结果变成了Double类型。这不是我们想要的结果,极端情况,数字精确度还会变化。</p>
<h3>Case 9</h3>
<p>最后,我们看一个数据失真的Case</p>
<p>准备测试数据</p>
<div class="cnblogs_code">
<pre>db.testnumber.insert({    ts1 : NumberDecimal("1747.872"),ts2 : NumberDecimal("51.408"),tst : NumberDecimal("123"))})</pre>
</div>
<p>执行更新(在<strong>nosqlbooster 执行的</strong>)</p>
<div class="cnblogs_code">
<pre>    db.testnumber.find({}).forEach(function(item){   item.tst = item.ts1- item.ts2 ;db.testnumber.save(item) })</pre>
</div>
<p>更新后的数据</p>
<div class="cnblogs_code">
<pre>{ "_id" : ObjectId("5d5b922744b6e6393c6c7693"), "ts1" : NumberDecimal("1747.872"), "ts2" : NumberDecimal("51.408"), "tst" : 1696.4640000000002 }</pre>
</div>
<p>tst 字段,变成了Double类型,且<strong>计算后的结果是不准确的。</strong></p>
<h3>7.保持Decimal 字段类型及精度的尝试</h3>
<p>那么有没有其他写法,可以保证更新前后数据类型不变并且不会失真呢?</p>
<h4><strong>7.1先寻找保持数据类型不变的方法</strong></h4>
<p>如果是&nbsp;nosqlbooster 工具,将要更新的字段保留为NumberDecimal,其操作命令如下:</p>
<div class="cnblogs_code">
<pre> db.testnumber.<span style="color: rgba(0, 0, 255, 1)">find</span>({}).forEach(<span style="color: rgba(0, 0, 255, 1)">function</span>(item){   db.testnumber.update({<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span>:item._id},{$set:{<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tst</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="font-size: 18px"><strong><span style="color: rgba(255, 0, 0, 1)">NumberDecimal</span><span style="color: rgba(255, 0, 0, 1)">(</span></strong></span><strong><span style="font-size: 16px; color: rgba(255, 0, 0, 1)">String(</span></strong>item.ts1 - item.ts2<span style="font-size: 16px"><strong><span style="color: rgba(255, 0, 0, 1)">)</span></strong></span><span style="color: rgba(255, 0, 0, 1)"><strong><span style="font-size: 18px">)</span></strong></span>}})})</pre>
</div>
<p>查看更新的结果</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819173224123-1346781891.png"></p>
<p>但是<strong>这个命令是不可以在 mongo shell 段执行的</strong>,测试如下:</p>
<p>在mongo shell执行如下命令:</p>
<div class="cnblogs_code">
<pre>db.testnumber.<span style="color: rgba(0, 0, 255, 1)">find</span>({}).forEach(<span style="color: rgba(0, 0, 255, 1)">function</span>(item){   db.testnumber.update({<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span>:item._id},{$set:{<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tst</span><span style="color: rgba(128, 0, 0, 1)">"</span>:NumberDecimal(String(item.ts1 - item.ts2))}})})</pre>
</div>
<p>更新结果如下:</p>
<p><img src="https://img2018.cnblogs.com/blog/780228/201908/780228-20190819173446466-2080422109.png"></p>
<p>上面的数据类型虽然是Decimal,但是数字是NAN。所以不能更新执行。</p>
<h4><strong>&nbsp;7.2 数据不失真问题</strong></h4>
<p>还是使用上面第6 部分的Case 数据。</p>
<p>测试前的数据</p>
<div class="cnblogs_code">
<pre>db.testnumber.insert({    ts1 : NumberDecimal("1747.872"),ts2 : NumberDecimal("51.408"),tst : NumberDecimal("123"))})</pre>
</div>
<p>执行更新(在<strong>nosqlbooster 执行的</strong>)</p>
<div class="cnblogs_code">
<pre>&nbsp;db.testnumber.find({}).forEach(function(item){&nbsp; &nbsp;db.testnumber.update({"_id":item._id},{$set:{"tst":NumberDecimal(String(item.ts1 - item.ts2))}})})</pre>
</div>
<p>更新后的数据</p>
<div class="cnblogs_code">
<pre>{ "_id" : ObjectId("5d5b922744b6e6393c6c7693"), "ts1" : NumberDecimal("1747.872"), "ts2" : NumberDecimal("51.408"), "tst" : NumberDecimal("1696.4640000000002") }</pre>
</div>
<p>tst 字段,已经变成了Decimal类型,但<strong>计算后的结果是不准确的。</strong></p>
<p>我们在开篇讲过,原来的数据都是保存了Decimal(18,4)的格式,所以,如果在mongo 命令上添加四舍五入的函数 toFixed(n) , n为要保留的小数位数。</p>
<div class="cnblogs_code">
<pre> db.testnumber.<span style="color: rgba(0, 0, 255, 1)">find</span>({}).forEach(<span style="color: rgba(0, 0, 255, 1)">function</span>(item){   db.testnumber.update({<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span>:item._id},{$set:{<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tst</span><span style="color: rgba(128, 0, 0, 1)">"</span>:NumberDecimal(String((item.ts1 - item.ts2)<span style="color: rgba(255, 0, 0, 1)"><strong><span style="font-size: 18px">.toFixed(4)</span></strong></span>))}})})</pre>
</div>
<p>查询结果</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : ObjectId(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">5d5b922744b6e6393c6c7693</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts1</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1747.872</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ts2</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">51.408</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tst</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1696.4640</span><span style="color: rgba(128, 0, 0, 1)">"</span>) }</pre>
</div>
<p><strong><span style="color: rgba(255, 0, 0, 1)">这个结果才是我们真正想要的结果。</span></strong></p>
<h3>8.不同数字类型下的比较 查询&nbsp;</h3>
<p>测试案例所需数据</p>
<div class="cnblogs_code">
<pre>db.testnumno.insert({ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal( <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">9.99</span><span style="color: rgba(128, 0, 0, 1)">"</span> ), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Decimal</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> })
db.testnumno.insert({ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">2</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">9.99</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Double</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> })
db.testnumno.insert({ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">3</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">10</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Double</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> })
db.testnumno.insert({ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">4</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberLong(<span style="color: rgba(128, 0, 128, 1)">10</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Long</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> })
db.testnumno.insert({ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">5</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal( <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10.0</span><span style="color: rgba(128, 0, 0, 1)">"</span> ), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Decimal</span><span style="color: rgba(128, 0, 0, 1)">"</span> })</pre>
</div>
<p><strong>Case 1&nbsp;</strong></p>
<p>执行查询</p>
<div class="cnblogs_code">
<pre>db.testnumno.<span style="color: rgba(0, 0, 255, 1)">find</span>({ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">9.99</span> })</pre>
</div>
<p>返回结果</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">2</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">9.99</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Double</span><span style="color: rgba(128, 0, 0, 1)">"</span> }</pre>
</div>
<p>直接输入数字,默认是Double类型,在算法表示上 double 类型的9.99 和 Decimal 类型的9.99 是不相等的。查询结果只有一条数据。</p>
<p><strong>Case 2</strong></p>
<p>执行查询</p>
<div class="cnblogs_code">
<pre>db.testnumno.<span style="color: rgba(0, 0, 255, 1)">find</span>({ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span>: NumberDecimal( <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">9.99</span><span style="color: rgba(128, 0, 0, 1)">"</span> ) })</pre>
</div>
<p>返回结果</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">9.99</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Decimal</span><span style="color: rgba(128, 0, 0, 1)">"</span> }</pre>
</div>
<p>返回一条结果的原因和Case 1 相同。</p>
<p><strong>Case 3&nbsp;</strong></p>
<p>执行查询</p>
<div class="cnblogs_code">
<pre>db.testnumno.<span style="color: rgba(0, 0, 255, 1)">find</span>({val: <span style="color: rgba(128, 0, 128, 1)">10</span> })</pre>
</div>
<p>返回结果</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">3</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">10</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Double</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> }
{ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">4</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberLong(<span style="color: rgba(128, 0, 128, 1)">10</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Long</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> }
{ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">5</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10.0</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Decimal</span><span style="color: rgba(128, 0, 0, 1)">"</span> }</pre>
</div>
<p><strong>Case 4</strong></p>
<p>执行查询</p>
<div class="cnblogs_code">
<pre>db.testnumno.<span style="color: rgba(0, 0, 255, 1)">find</span>({ val: NumberDecimal( <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10</span><span style="color: rgba(128, 0, 0, 1)">"</span> ) })</pre>
</div>
<p>返回结果</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">3</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">10</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Double</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> }
{ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">4</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberLong(<span style="color: rgba(128, 0, 128, 1)">10</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Long</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> }
{ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">5</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10.0</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Decimal</span><span style="color: rgba(128, 0, 0, 1)">"</span> }</pre>
</div>
<p><strong>Case 5</strong></p>
<p>执行查询</p>
<div class="cnblogs_code">
<pre>db.testnumno.<span style="color: rgba(0, 0, 255, 1)">find</span>({ val: NumberDecimal( <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10.0</span><span style="color: rgba(128, 0, 0, 1)">"</span> ) })</pre>
</div>
<p>返回结果</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">3</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">10</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Double</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> }
{ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">4</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberLong(<span style="color: rgba(128, 0, 128, 1)">10</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Long</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> }
{ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">5</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">val</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberDecimal(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10.0</span><span style="color: rgba(128, 0, 0, 1)">"</span>), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Decimal</span><span style="color: rgba(128, 0, 0, 1)">"</span> }</pre>
</div>
<p>&nbsp;</p>
<p>Case 3、Case 4 、Case 5 表明,在表达整数时,doubel 、Decimal 、Long 三者在算法表达上相等。</p>
<p>以上 5 个Case 在Mongo shell、nosqlbooster 演示结果一样。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3>&nbsp;参考文献:</h3>
<p>https://docs.microsoft.com/en-us/dotnet/api/system.double?redirectedfrom=MSDN&amp;view=netframework-4.8</p>
<p>https://docs.mongodb.com/manual/core/shell-types/</p>
<p>https://docs.mongodb.com/manual/reference/operator/query/type/index.html</p>
<p>https://www.jianshu.com/p/6b51adc05203</p>
<p>https://stackoverflow.com/questions/5314238/how-do-i-set-the-serialization-options-for-the-geo-values-using-the-official-10g</p>
<p>&nbsp;https://www.213.name/archives/1147</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong><strong><strong>本文版权归作者所有,未经作者同意不得转载</strong><strong>,</strong><strong>谢谢配合!!!</strong></strong></strong></p><br><br>
来源:https://www.cnblogs.com/xuliuzai/p/11365739.html
頁: [1]
查看完整版本: 谨慎 mongodb 关于数字操作可能导致类型及精度变化