Skip to main content
 首页 » 编程设计

MongoDB之$setIntersection 与 $facet

2025年05月04日69arxive

这是我的查询:

db.movies.aggregate([ 
   {$facet:{ 
        rating:[{$match: {"imdb.rating":{$gte: 0},"metacritic":{$gte: 0}}},  
   {$sort: {"imdb.rating":-1}},{$project:  
   {"title":1,"imdb.rating":1,"metacritic":1}},{$limit: 10}], 
 
     critic:[{$match: {"metacritic":{$gte: 0},"imdb.rating":{$gte: 0}}},  
   {$sort: {"metacritic": -1}},{$project:  
   {"title":1,"imdb.rating":1,"metacritic":1}},{$limit: 10}], 
 
     intersection:[{$project: {common: {$setIntersection:  
   ["$rating","$critic"]}}}] 
 
 }} 
 
 
]) 

我的样本数据集是:
{ 
"_id" : ObjectId("573a13cef29313caabd8709c"), 
"title" : "Justin Bieber: Never Say Never", 
"year" : 2011, 
"runtime" : 105, 
"released" : ISODate("2011-02-11T00:00:00.000Z"), 
"cast" : [  
    "Justin Bieber",  
    "Boys II Men",  
    "Miley Cyrus",  
    "Sean Kingston" 
], 
"metacritic" : 52, 
"poster" : "http://ia.media-imdb.com/images/M/MV5BMTY0NDQzMjIzOF5BMl5BanBnXkFtZTcwNDk2NzczNA@@._V1_SX300.jpg", 
"plot" : "Follows Justin Bieber with some footage of performances from his 2010 concert tour.", 
"fullplot" : "The camera follows Justin Bieber (1994- ) during the ten days leading up to his August, 2010, sold-out show at Madison Square Garden. Footage of these ten days of concerts, rehearsals, and down time with boyhood friends, his mom, and his entourage is inter-cut with home movies, old photos, and interviews showing a musical prodigy who loves to perform, comes to the attention of an Atlanta agent via YouTube, impresses Usher, and rockets to international stardom soon after his 15th birthday. His manager emphasizes the importance of social media and of Justin's work ethic and personality in making him a star; the camera emphasizes Bieber's look. His mom and grandparents shine.", 
"awards" : "2 wins & 6 nominations.", 
"lastupdated" : "2015-08-23 00:33:04.327000000", 
"type" : "movie", 
"languages" : [  
    "English" 
], 
"directors" : [  
    "Jon M. Chu" 
], 
"imdb" : { 
    "rating" : 1.6, 
    "votes" : 73548, 
    "id" : 1702443 
}, 
"countries" : [  
    "USA" 
], 
"rated" : "G", 
"genres" : [  
    "Documentary",  
    "Music" 
], 
"tomatoes" : { 
    "website" : "http://www.JustinBieberNeverSayNever.com", 
    "viewer" : { 
        "rating" : 3.5, 
        "numReviews" : 61961, 
        "meter" : 65 
    }, 
    "dvd" : ISODate("2011-05-13T00:00:00.000Z"), 
    "rotten" : 37, 
    "boxOffice" : "$73.0M", 
    "consensus" : "As a tour documentary, it's rather uninspired -- but as a 3D glimpse of a building pop culture phenomenon, Never Say Never is undeniably entertaining.", 
    "critic" : { 
        "rating" : 5.8, 
        "numReviews" : 102, 
        "meter" : 64 
    }, 
    "production" : "Paramount Pictures", 
    "lastUpdated" : ISODate("2015-08-18T19:05:06.000Z"), 
    "fresh" : 65 
}, 
"num_mflix_comments" : 2, 
"comments" : [  
    { 
        "name" : "Petyr Baelish", 
        "email" : "aidan_gillen@gameofthron.es", 
        "movie_id" : ObjectId("573a13cef29313caabd8709c"), 
        "text" : "A earum quae quos perspiciatis tempora natus. Voluptatem quod cum illum magni reiciendis. Labore exercitationem velit suscipit dicta.", 
        "date" : ISODate("2009-05-10T13:15:19.000Z") 
    },  
    { 
        "name" : "Daario Naharis", 
        "email" : "michiel_huisman@gameofthron.es", 
        "movie_id" : ObjectId("573a13cef29313caabd8709c"), 
        "text" : "Ut quod rem rem dolor voluptatum necessitatibus sapiente. Ea nulla dignissimos iste porro natus eveniet eum. Quidem sit totam libero iusto repudiandae ab ducimus. Facere nesciunt assumenda ab.", 
        "date" : ISODate("1992-02-17T22:39:11.000Z") 
    } 
] 
} 

我正在尝试查找 中的电影两个 :
列表 1) 根据 imdb 评分排名前 10 的电影
list 2) Metacritic 排名前 10 的电影

如果在两个列表中都看到一部电影或多部电影,则应过滤并显示这些电影。
intersection:[{$project: {common: {$setIntersection:["$rating","$critic"]}}}]
这部分不起作用,我什至尝试匹配标题 $setIntersection:["$rating.title","$critic.title"]
我看到数组( ratingcriticcommon )是单独计算的,但是为什么我不能用 $ 访问这些数组作为变量?有人可以告诉我如何获得 rating的交集吗?和 critic ?

请您参考如下方法:

你的方法没问题,我认为通过重新定位你的括号你会得到你想要的。分开$project进入另一个阶段,而不是 $facet 中的另一个阶段:

db.movies.aggregate([{ 
    $facet:{ 
        rating:[ 
            {$match:{"imdb.rating":{$gte: 0},"metacritic":{$gte: 0}}}, 
            {$sort:{"imdb.rating":-1}}, 
            {$project:{"title":1,"imdb.rating":1,"metacritic":1}}, 
            {$limit:10} 
        ], 
        critic:[ 
            {$match:{"metacritic":{$gte: 0},"imdb.rating":{$gte: 0}}},  
            {$sort:{"metacritic": -1}}, 
            {$project:{"title":1,"imdb.rating":1,"metacritic":1}}, 
            {$limit:10} 
        ] 
    } 
}, { 
    $project:{ 
        common:{$setIntersection:["$rating","$critic"]} 
    } 
}]) 

需要这样做的原因可以在 documentation 中找到。 :

Each sub-pipeline within $facet is passed the exact same set of input documents. These sub-pipelines are completely independent of one another and the document array output by each is stored in separate fields in the output document. The output of one sub-pipeline can not be used as the input for a different sub-pipeline within the same $facet stage. If further aggregations are required, add additional stages after $facet and specify the field name, , of the desired sub-pipeline output.