填充了Mongoose排序子文档

时间:2016-04-24 15:08:11

标签: node.js mongodb sorting mongoose-populate

我有一个Mongoose模型,其中包含需要填充的路径:

var adsSchema = new Schema({                                                                   
    price:      { type: Number, min: 0, required: true }, 
    author:     { type: ObjectId, ref: 'Users', required: true }, 
    title:      { type: String, required: true }, 
    date:       { type: Date, default: Date.now }, 
    offers:     [{                                
        price:      { type: Number, required: true },                                          
        date:       { type: Date, default: Date.now },                                         
        offerBy:    { type: ObjectId, ref: 'Users', required: true }                           
    }],                                                                                        
    category:   { type: ObjectId },                                                            
    images:     [{                                                                             
        type: ObjectId,                                                                        
        ref: 'Images'                                                                          
    }],                                                                                        
    videos:     [String]                                                                       
});

在某些GET请求中,我需要按照我的说法填充多个字段,特别是按“价格”按升序排序。

当Mongoose的文档显示在那里(http://mongoosejs.com/docs/api.html#query_Query-populate)时,您可以按子路径排序。

我的问题是情况并非如此。

我的代码正在执行:

Ads.findOne({ _id: adId })
  .populate({ path: 'author', select: 'firstName lastName' })
  .populate('images')
  .populate({ path: 'offers', options: { sort: { 'price': -1 } })
  .populate({ path: 'category', select: 'name' })
  .exec(function (err, ad) {
     if (err)
       deferred.reject({ status: 500, message: 'Database error.' });
     else if (!ad)
       deferred.reject({ status: 500, message: 'The ad doesn\'t exist!.' });
     else {
                deferred.resolve(ad.toJSON());
     }
})

我已经在这里或在Mongoose邮件列表中阅读了尽可能多的问题/答案:

我知道不可能从子文档结果中排序文档结果,OK。但我只想对那个子文档进行排序,只有这一个。这里的一些回答似乎表明它是可能的:

我有2个问题:

  • 是否有可能(编写Mongoose文档时)在人口中对子文档进行排序?
  • 是否与我不仅仅将ObjectId链接到其他Schema的事实相关联?

感谢您的回答;)

2 个答案:

答案 0 :(得分:0)

就个人而言,我不尽可能使用'populate'。我过去经历过很多麻烦。所以,我不知道如何在填充时进行排序。

您可以在聚合中使用$ lookup方法,而不是使用populate,您可以轻松地对任何字段进行排序。与“人口”几乎相同。

<form method="POST" enctype="multipart/form-data"> <!-- remove action ='#' -->
from:
<select name="age_from" id="age_a" onchange="checkages_a()"> 
    <option value=""></option>
    <?php
        for($i = 17; $i <= 50; ++$i) {
            if(isset($_POST['age_from']) && $_POST['age_from'] == $i){ // to make selected value to be  selected even after form submit
                echo "\t", '<option value="', $i. '" selected ="selected">', $i, '</option>', "\n";
            }else{
                echo "\t", '<option value="', $i. '">', $i, '</option>', "\n";
            }
        }
    ?>
</select>
to: 
<select name="age_to" id="age_b" onchange="checkages_b()"> 
    <option value=""></option>
    <?php
        for($i = 18; $i <= 50; ++$i) {
            if(isset($_POST['age_to']) && $_POST['age_to'] == $i){// to make selected value to be  selected even after form submit
                echo "\t", '<option value="', $i. '" selected ="selected">', $i, '</option>', "\n";
            }else{
                echo "\t", '<option value="', $i. '">', $i, '</option>', "\n";
            }
        }
    ?>
</select>
<input type="radio" name="gender" value="male">Male</input> <br />
<input type="radio" name="gender" value="female">Female</input><br />
<input type="submit" class="btn btn-info" name="submit_form" value="Click to start chat! " />
<form>

<?php 

$refined_gender = isset($_POST['gender']) ? $_POST['gender'] : ''; // escape gives me undefined function error at my end so i removed it, but if it is working at your end thhen keep it up as it is.
$age_from       = isset($_POST['age_from']) ? $_POST['age_from'] : '';
$age_to         = isset($_POST['age_to']) ? $_POST['age_to'] : '';

if (empty ($refined_gender) && empty($age_from) && empty ($age_to)) { // check always with form posted value not submit button value and also cange || to &&
    echo "<div class='no_user'><p> Please apply at least one of the filters above. </p> </div>";
} else {
// search user
}
?>

我没有正确检查所有字段。请以这种方式实现您的模型,希望这可以给您一些想法。祝你好运

答案 1 :(得分:0)

我找到了解决方案,这是我第二个问题的回应。

当您在架构中编写子文档时,就像在我的问题中一样,您没有创建&#34;关系&#34;在一个模型和另一个模型之间。这意味着填充方法根本不起作用。

您必须引用ObjectId以及与之相关联的模型以便能够使用populate,以及为您提供Mongoose的选项。这是一个例子:

var adsSchema = new Schema({
    price:      { type: Number, min: 0, required: true },
    author:     { type: ObjectId, ref: 'Users', required: true },
    offers:     [{ 
        type: ObjectId,
        ref: 'Offers'
    }],
    videos:     [String]
});

现在,.populate方法正常工作,因为Mongoose(以及MongoDB)可以在其他Collection上执行子查询并对其进行排序。事情并非如此,因为它在同一个模型中,因此Mongoose不会在同一个集合上执行子查询(我似乎理解它)。