不知道如何使用 MongoDB 的 $bitsAnySet 运算符

Can't figure out how to use MongoDB's $bitsAnySet operator

我正在做一个小项目,我需要在我的 MongoDB 数据库中存储营业时间。我决定为整个星期使用一个位掩码,由 336 位表示,这意味着每一位代表一天中的 30 分钟。 (使用位掩码没有特殊原因。我愿意改变我存储营业时间的方式,但我很好奇。)

我认为如果我使用 $bitsAnySet 运算符基于位掩码进行查询会很方便,因为如果客户在下午 4 点查询营业时间,我可以找出需要设置的位置例如。

阅读 docs about the operator 我发现您可以提供一组要检查的位置,这将非常适合我的需要。

但这就是问题所在。我无法弄清楚这些职位是如何运作的。 文档状态,位置 0 将位于最低有效位(最右边的位),这意味着如果查询 $bitsAnySet: [0],将找不到存储为营业时间的数字如 254 (0b1111 1110) 的文档:因为在这个例子中最右边的位被设置为 0。

以这种方式使用运算符,在我的测试数据上进行测试我总是运行遇到问题,因为定位似乎不匹配。

所以我给自己写了一个小脚本(在 JavaScript 运行 on NodeJS v12 connecting to MongoDB using Mongoose)只是尝试所有可能的位置:

这是我的脚本:

require ('mongoose').connect ('mongodb://localhost/test', {useCreateIndex: true, useNewUrlParser: true, useFindAndModify: false, useUnifiedTopology: true}).then (() => {

    let buffer = Buffer.alloc (6, 0);

    // 0xC0 => 0b1100 0000
    buffer.writeUInt8 (0xC0, 0);
    // 0x07 => 0b0000 0111
    buffer.writeUInt8 (0x07, 5);

    // buffer should be: 11000000 00000000 00000000 00000000 00000000 00000111

    new SomeModel ({data: buffer}).save ().then (model => {

        let promises = [];

        // just trying out each position
        for (let index = 0; index < 48; index ++)
            promises.push (SomeModel.findOne ({data: {$bitsAnySet: [index]}}))

        Promise.all (promises).then (resolved => {

            resolved = resolved.map ((item, index) => {
                if (item !== null)
                    return {index, item: item.data.toString ('hex')};
                else return null;
            });

            // yes, I know it's not very performant to go over the entire array a second time,
            // because I could have done it in the first round, 
            // but this was just some quick and dirty testing :D
            resolved = resolved.filter (item => item !== null);
            console.log (resolved);

        }) 

    }).catch (console.log);

}).catch (console.log);

这是我的小测试脚本,我希望输出如下:

[
 {index: 0, item: 'c00000000007'},
 {index: 1, item: 'c00000000007'},
 {index: 2, item: 'c00000000007'},

 {index: 41, item: 'c00000000007'},
 {index: 42, item: 'c00000000007'},
]

因为从右边看二进制表示时,它应该首先找到位置 0、1 和 2 的三个,然后它应该在最左端找到最后两个。

但是我得到了这个:

[
  { index: 6, item: 'c00000000007' },
  { index: 7, item: 'c00000000007' },

  { index: 40, item: 'c00000000007' },
  { index: 41, item: 'c00000000007' },
  { index: 42, item: 'c00000000007' }
]

这让我大吃一惊,因为这对我来说是完全出乎意料的。突然开始看起来 MongoDB 是从左边开始的。它在三个之前找到了两个,并且两个位于二进制数据的最左侧。让我感到困惑的是它似乎不是从位置 0 开始的。

如果我没记错的话,我的数据以两个开始,以三个结束。所以 $bitsAnySet: [0] 应该是正确的。

你们有人知道我在这里做错了什么吗? 非常感谢您的帮助!

注意:如果我错了请纠正我,但我相信Promise.all不会改变数组的顺序,这意味着它不能只是是一个承诺在另一个改变其在 'promises' 数组中的位置之前刚刚解决。

注意:该模型没有任何附加字段。它只有默认的 _id 字段和数据字段。

幸运的是我自己解决了这个问题。 这与字节顺序有关。在我看来,我正在考虑大端方式,因此假设它存储如下:

Hex: c0 00 00 00 00 07

Bin: 11000000 00000000 00000000 00000000 00000000 00000111

根据BSON SpecificationBSON是

serialized in little-endian format.

因此它实际上是这样存储的:

Hex: 07 00 00 00 00 C0

Bin: 00000111 00000000 00000000 00000000 00000000 11000000

这解释了为什么索引会混在一起。