从MongoDB集合中返回随机文档样本的3种方法

发布于

如果需要从集合中返回一小部分随机文档示例,可以使用聚合管道尝试以下三种方法。

舞台$sample

聚合管道阶段专门设计用于随机选择指定数量的文档。[$sample](https://database.guide/mongodb-sample/ "MongoDB $sample")

使用 时,可以指定要在字段中返回的文档数。$sample``size

假设我们有以下集合,名为:pets

{ “_id” : 1, “name” : “Wag”, “type” : “Dog”, “weight” : 20 } { “_id” : 2, “name” : “Bark”, “type” : “Dog”, “weight” : 10 } { “_id” : 3, “name” : “Meow”, “type” : “Cat”, “weight” : 7 } { “_id” : 4, “name” : “Scratch”, “type” : “Cat”, “weight” : 8 } { “_id” : 5, “name” : “Bruce”, “type” : “Bat”, “weight” : 3 } { “_id” : 6, “name” : “Hop”, “type” : “Kangaroo”, “weight” : 130 } { “_id” : 7, “name” : “Punch”, “type” : “Gorilla”, “weight” : 300 } { “_id” : 8, “name” : “Snap”, “type” : “Crocodile”, “weight” : 400 } { “_id” : 9, “name” : “Flutter”, “type” : “Hummingbird”, “weight” : 1 }

我们可以像这样随机抓取这些文档的样本:$sample

db.pets.aggregate( [ { $sample: { size: 3 } } ] )

输出:

{ "_id" : 1, "name" : "Wag", "type" : "Dog", "weight" : 20 }
{ "_id" : 5, "name" : "Bruce", "type" : "Bat", "weight" : 3 }
{ "_id" : 3, "name" : "Meow", "type" : "Cat", "weight" : 7 }

在本例中,我指定了返回三个文档。{ size: 3 }

这里再次使用不同的样本大小:

db.pets.aggregate(
   [
      { 
        $sample: { size: 5 } 
      }
   ]
)

输出:

{ "_id" : 6, "name" : "Hop", "type" : "Kangaroo", "weight" : 130 }
{ "_id" : 5, "name" : "Bruce", "type" : "Bat", "weight" : 3 }
{ "_id" : 8, "name" : "Snap", "type" : "Crocodile", "weight" : 400 }
{ "_id" : 7, "name" : "Punch", "type" : "Gorilla", "weight" : 300 }
{ "_id" : 4, "name" : "Scratch", "type" : "Cat", "weight" : 8 }

阶段以两种方式之一工作,具体取决于集合中的文档数、相对于集合中文档数的样本大小及其在管道中的位置。请参阅 MongoDB $sample 了解其工作原理。$sample

该阶段也可能在其结果集中多次返回同一文档。$sample

运营商$rand

该运算符是在 MongoDB 4.4.2 中引入的,其目的是在每次调用时返回 0 到 1 之间的随机浮点数。$rand

因此,我们可以在阶段中与其他运算符结合使用,例如 和 返回文档的随机样本。$match``$expr``$lt

例:

db.pets.aggregate(
   [
      { 
        $match: 
          { 
            $expr: 
              { 
                $lt: [ 0.5, { $rand: {} } ] 
              }
          } 
      }
   ]
)

输出:

{ "_id" : 3, "name" : "Meow", "type" : "Cat", "weight" : 7 }
{ "_id" : 4, "name" : "Scratch", "type" : "Cat", "weight" : 8 }
{ "_id" : 6, "name" : "Hop", "type" : "Kangaroo", "weight" : 130 }
{ "_id" : 9, "name" : "Flutter", "type" : "Hummingbird", "weight" : 1 }

此方法的结果集与该方法不同,因为它不返回固定数量的文档。使用此方法返回的文档数可能会有所不同。$sample

例如,当我多次运行相同的代码时,会发生什么情况。

结果集 2:

{ “_id” : 1, “name” : “Wag”, “type” : “Dog”, “weight” : 20 } { “_id” : 7, “name” : “Punch”, “type” : “Gorilla”, “weight” : 300 } { “_id” : 8, “name” : “Snap”, “type” : “Crocodile”, “weight” : 400 }

结果集 3:

{ “_id” : 2, “name” : “Bark”, “type” : “Dog”, “weight” : 10 } { “_id” : 4, “name” : “Scratch”, “type” : “Cat”, “weight” : 8 } { “_id” : 9, “name” : “Flutter”, “type” : “Hummingbird”, “weight” : 1 }

结果集 4:

{ “_id” : 1, “name” : “Wag”, “type” : “Dog”, “weight” : 20 } { “_id” : 3, “name” : “Meow”, “type” : “Cat”, “weight” : 7 } { “_id” : 6, “name” : “Hop”, “type” : “Kangaroo”, “weight” : 130 } { “_id” : 8, “name” : “Snap”, “type” : “Crocodile”, “weight” : 400 }

结果集 5:

{ “_id” : 1, “name” : “Wag”, “type” : “Dog”, “weight” : 20 } { “_id” : 4, “name” : “Scratch”, “type” : “Cat”, “weight” : 8 } { “_id” : 7, “name” : “Punch”, “type” : “Gorilla”, “weight” : 300 } { “_id” : 8, “name” : “Snap”, “type” : “Crocodile”, “weight” : 400 } { “_id” : 9, “name” : “Flutter”, “type” : “Hummingbird”, “weight” : 1 }

运营商$sampleRate

在MongoDB 4.4.2中引入的运算符提供了一种与前面的示例相同的更简洁的方法。$sampleRate

使用 时,提供采样率作为介于 和 之间的浮点数。选择过程使用均匀随机分布,您提供的采样率表示给定文档在通过管道时被选中的概率。$sampleRate``0``1

例:

db.pets.aggregate(
   [
      { 
        $match: { $sampleRate: 0.5 } 
      }
   ]
)

输出:

{ "_id" : 1, "name" : "Wag", "type" : "Dog", "weight" : 20 }
{ "_id" : 2, "name" : "Bark", "type" : "Dog", "weight" : 10 }
{ "_id" : 5, "name" : "Bruce", "type" : "Bat", "weight" : 3 }
{ "_id" : 6, "name" : "Hop", "type" : "Kangaroo", "weight" : 130 }
{ "_id" : 7, "name" : "Punch", "type" : "Gorilla", "weight" : 300 }
{ "_id" : 8, "name" : "Snap", "type" : "Crocodile", "weight" : 400 }

然后再次运行它:

{ “_id” : 3, “name” : “Meow”, “type” : “Cat”, “weight” : 7 } { “_id” : 4, “name” : “Scratch”, “type” : “Cat”, “weight” : 8 } { “_id” : 7, “name” : “Punch”, “type” : “Gorilla”, “weight” : 300 } { “_id” : 8, “name” : “Snap”, “type” : “Crocodile”, “weight” : 400 } { “_id” : 9, “name” : “Flutter”, “type” : “Hummingbird”, “weight” : 1 }

再说一遍:

{ “_id” : 1, “name” : “Wag”, “type” : “Dog”, “weight” : 20 } { “_id” : 2, “name” : “Bark”, “type” : “Dog”, “weight” : 10 } { “_id” : 3, “name” : “Meow”, “type” : “Cat”, “weight” : 7 } { “_id” : 8, “name” : “Snap”, “type” : “Crocodile”, “weight” : 400 }