简体   繁体   English

mongoose find() 在 js 中对来自产品数据库的返回结果进行排序和组织

[英]mongoose find() sorting and organizing returned results from a product database in js

I have a problem with organizing my mongoDB data to send to my page in my res and cant figure out how to do the correct js.我在组织 mongoDB 数据以发送到我的资源页面时遇到问题,并且无法弄清楚如何执行正确的 js。 Here is a simplified version of my schema这是我的架构的简化版本

var productSchema = new mongoose.Schema({

medium:     String,
brand:      String,
group:      String

}); });

Here is what a typical entry looks like这是典型条目的样子

 medium :"Acrylic",
 brand  :"liquitex",
 group  :"heavy body"

there are many more entries in the schema, but these are the only ones I need to be able to sort and organize the returned results with.模式中有更多条目,但这些是我唯一需要能够对返回的结果进行排序和组织的条目。 The problem is I have a route that returns all colors in my database and I want to be able to display them in sections on my page that are grouped under Brand, and then has the individual colors listed under the correct group.问题是我有一个返回数据库中所有颜色的路由,我希望能够在页面上按品牌分组的部分中显示它们,然后在正确的组下列出各个颜色。

The problem is there are paints from other brands that fall into the heavy body group and so when I use a filter function to sort my data by group, some brands get mixed together.问题是其他品牌的油漆属于重体组,因此当我使用过滤器功能按组对数据进行排序时,一些品牌会混在一起。 I cant filter by brand, because some brands have acrylic and watercolor so then those get lumped together.我不能按品牌过滤,因为有些品牌有亚克力和水彩,所以它们会混在一起。 I need some way to filter the returned results of a我需要一些方法来过滤返回的结果

mongoose.find({})

that can use the group data as a filter, but then filter those results by the brands so they get separated into the correct brand categories.可以使用组数据作为过滤器,然后按品牌过滤这些结果,以便将它们分成正确的品牌类别。

I have this so far:到目前为止我有这个:

this is all a stripped down version of my app.js file:这是我的 app.js 文件的精简版:

    //finds all colors in the DB
    Color.find({}).lean().exec(function( err, colors)

                var groups  = [];
                // find all groups in the databse
                colors.forEach( function(color){    
                    groups.push(color["group"]);
                }); 


    //returns only unique names to filter out duplicates
                var groupTypes  = Array.from(new Set(groups));



            var tempVariableBrands = [];
// this sorts all returned paints into their respective group, but we get paints from multiple brands under the same group and that is not good
            groupTypes.forEach( function(group){
                            var name = group;
                            var result = colors.filter(obj => { return obj.group === group });
                            tempVariable.push(  {group : name, result } );      
                        });


        // the tempVariable gets sent to my page like so
        res.render("landing", {colorEntry:tempVariable} );

and this works fine to allow me to display each paint by its grouping, but that fails when there is more than one paint from a different manufacturer that is considered the same group like a "heavy body".这很好地允许我按其分组显示每种油漆,但是当来自不同制造商的不止一种油漆被认为是“重体”一样的同一组时,这种方法就会失败。 This is my ejs on my page that works fine:这是我的页面上的 ejs 工作正常:

<% colorEntry.forEach( function(entry){ %>                  
                    <div class="brandBlock">                        
                        <div class="brandTitle">
    <span><%=entry.result[0].brand%> - <%=entry.result[0].group%></span> 

I for the life of me cant seem to figure out the combination of filter() and maybe map() that would allow this kind of processing to be done.我一生似乎都无法弄清楚 filter() 和 map() 的组合可以完成这种处理。 My database has like 600 documents, colors from a number of different manufacturers and I don't know how to get this as a returned structure: lets say this is a few colors in the DB that get returned from a mongoose find:我的数据库有大约 600 个文档,来自许多不同制造商的颜色,我不知道如何将其作为返回的结构获取:假设这是从猫鼬查找返回的数据库中的几种颜色:

[{ medium: "Oil",
   brand: "Gamblin",
   group: "Artists oil colors"},
 { medium: "Acrylic",
   brand: "Liquitex",
   group:  "Heavy Body"},
 { medium: "Acrylic",
   brand: "Golden",
   group: "Heavy Body"}
]

i need to organize it like this or something similar.我需要像这样或类似的东西来组织它。 It can be anything that just sorts this data into a basic structure like this, I am not confined to any set standard or anything, this is just for personal use and a site I am trying to build to learn more.它可以是任何将这些数据分类为这样的基本结构的东西,我不限于任何既定标准或任何东西,这仅供个人使用,我正在尝试建立一个站点以了解更多信息。

 returnedColors = [ { brand: "Gamblin", group: "Artists oil colors", { 50 paints colors returned} },
                    { brand: "liquitex" , group: "heavy body", { 20 paint colors returned } },
                    { brand:  "golden"  , group: "heavy body",{ 60 paint colors returned} }
                  ];

I am not a web developer and only write some web code every 6 months or so and have been trying how to figure this out for the last 2 days.我不是网络开发人员,每 6 个月左右只编写一些网络代码,并且在过去 2 天里一直在尝试如何解决这个问题。 I can't wrap my head around some of the awesome filter and map combo's i have seen and cant get this to work.我无法想象我见过的一些很棒的过滤器和地图组合,也无法让它发挥作用。 Any help or advice would be great.任何帮助或建议都会很棒。 I am sure there are many areas for improvement in this code, but everything was working up until I entered paints that were from different brands that had the same group type and i had to try to rewrite this sorting code to deal with it.我确信这段代码有很多需要改进的地方,但一切都在进行,直到我输入了来自不同品牌、具有相同组类型的油漆,我不得不尝试重写这个排序代码来处理它。 It boils down to needing to be able to iterate over the entire set of returned documents from the DB and then sort them based off 2 values.归结为需要能够遍历从数据库返回的整个文档集,然后根据 2 个值对它们进行排序。

UPDATE: I was able to get something that works and returns the data in the format that I need to be able to send it to my ejs file and display it properly.更新:我能够得到一些有效的东西,并以我需要能够将它发送到我的 ejs 文件并正确显示它的格式返回数据。 The code is rather ugly and probably very redundant, but it technically works.代码相当丑陋,可能非常多余,但从技术上讲它是有效的。 It starts off by using the group value to run over paints since each set of paints will have a group name, but can sometimes share a group name with a paint from another brand like "heavy body".它首先使用组值运行涂料,因为每组涂料都有一个组名,但有时可以与来自另一个品牌的涂料共享一个组名,例如“重体”。

groupTypes.forEach( function(group){
                    var name = group;
                    var result = colors.filter(obj => { return obj.group === group });                  

                    // this gets brand names per iteration of this loop so that we will know if more than one brand of paint
                    // has the same group identity.
                    var brands  = [];
                    result.forEach( function(color){    
                        brands.push(color["brand"]);    
                    }); 
                    // This filters the brand names down to a unique list of brands
                    var brandNames  = Array.from(new Set(brands));

                    // if there is more than one brand, we need to filter this into two separate groups

                    if( brandNames.length > 1){
                        //console.log("You have duplicates");

                        brandNames.forEach( x => {
                            var tmpResult = [...result];
                            var resultTmp = result.filter(obj => { return obj.brand === x });

                            result = resultTmp;
                            //console.log("FILTERED RESULT IS: ", result);
                            tempVariable.push(  {brand: x ,group : name, result } );
                            result  = [...tmpResult];
                        });
                    }else{                      
                        tempVariable.push(  {brand: result[0].brand ,group : name, result } );
                    }
                });

if anyone can reduce this to something more efficient, I would love to see the "better" way or "right" way of doing something like this.如果有人可以将其简化为更有效的方法,我很想看到做这样的事情的“更好”方式或“正确”方式。

UPDATE2更新2

Thanks to the answer below, I was put on the right track and was able to rewrite a bunch of that long code with this:多亏了下面的答案,我走上了正确的轨道,并且能够用这个重写一堆这么长的代码:

    Color.aggregate([       
    {
        $sort: { name: 1}
    },
    {
        $group: {
            _id: { brand: '$brand', group: '$group' },
            result: { $push: '$$ROOT' }
        }
    },
    { $sort: { '_id.brand': 1 } }

    ], function( err, colors){
    if(err){
        console.log(err);
    }else{
        res.render("landing", {colorEntry:colors, isSearch:1, codes: userCodes, currentUser: req.user, ads: vs.randomAds()} );
    }       
});

Much cleaner and appears to achieve the same result.更干净,似乎达到了相同的结果。

Since you're using MongoDB, "right" way is to utilize an Aggregation framework , precisely, $group stage.由于您使用的是 MongoDB,“正确”的方法是使用聚合框架,准确地说,是$group阶段。

Product.aggregate([{
    $group: {
        _id: { group: '$group', brand: '$brand' },
        products: { $push: '$$ROOT' }
    }
}])

This will output array of objects containing every combination of brand and group, and push all relevant products to corresponding subarray.这将输出包含品牌和组的每个组合的对象数组,并将所有相关产品推送到相应的子数组。

Combine it with $project and $sort stages to shape your data further.将它与$project$sort阶段结合起来,进一步塑造你的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM