聚合函数在页面刷新时复制 ng-repeat 中的项目。需要弄清楚如何停止重复。 Angularjs Mongodb mongoose

Posted

技术标签:

【中文标题】聚合函数在页面刷新时复制 ng-repeat 中的项目。需要弄清楚如何停止重复。 Angularjs Mongodb mongoose【英文标题】:Aggregate function duplicates items in ng-repeat on page refresh. Need to figure out how to stop the duplication. Angularjs Mongodb mongoose 【发布时间】:2015-03-22 20:31:23 【问题描述】:

我有一个集合中的项目,这些项目通过这个聚合来查找它们的平均评级,并在它们尚未被评论/评级时找到它们。

它可以工作,但是现在每次我刷新页面时,它都会在波旁酒系列中每个项目的 ng-repeat 中显示一个副本。波旁威士忌系列中的实际物品数量没有变化。我该如何阻止这个? 服务器端: 波旁模式:

'use strict';

var mongoose = require('mongoose'),
    BourbonSchema = null;

module.exports = mongoose.model('Bourbon', 
    name:  type: String, required: true,
    blog:  type: String, required: true,
    photo: type: String, required: true, default:'http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg',
    location: type: String, required: true,
    distillery: type: String, required: true,
    comments: [type: mongoose.Schema.ObjectId, ref: 'Comments'],
    rating : type: Number
);

var Bourbon = mongoose.model('Bourbon', BourbonSchema);
module.exports = Bourbon;

评论/评分架构:

'use strict';

var mongoose = require('mongoose');

module.exports = mongoose.model('Comment', 
    bourbonId:   type: mongoose.Schema.ObjectId, ref: 'Bourbon',
    userId:   type: mongoose.Schema.ObjectId, ref: 'User',
    text:     type: String, required: true,
    createdAt: type: Date,  required: true, default: Date.now,
    rating  : type: Number, required: true,
    votes:     type: Number, default: 0
);

聚合函数:

'use strict';

var Bourbon = require('../../../models/bourbon'),
    Comment = require('../../../models/comment'),
    DataStore = require('nedb'),
    db = new DataStore(),
    async = require('async');

module.exports = 
    description: 'Get Bourbons',
    notes: 'Get Bourbons',
    tags: ['bourbons'],
    handler: function(request, reply)

        async.series(
            [
                function(callback)
                    Bourbon.find(,function(err,results)
                        //if (err) callback(err);
                        async.eachLimit(results,10,function(result,callback)
                            var plain = result.toObject();
                            plain.bourbonId = plain._id.toString();
                            plain.avgRating = 0;
                            delete plain._id;

                            db.insert(plain,callback);
                        ,callback);
                    );
                ,

                function(callback)
                    Comment.aggregate(
                        [
                            $group:
                                _id: '$bourbonId',
                                avgRating:$avg:'$rating'
                            
                        ],
                        function(err,results)
                            async.eachLimit(results,10,function(result,callback)
                                db.update(
                                    bourbonId: result._id.toString(),
                                    $set: avgRating: result.avgRating,
                                    callback                   
                                );
                            ,callback);                 
                        
                    );
                
            ],

            function(err)
                //if (err) callback(err);
                db.find(, _id: 0, function(err, bourbons)
                    console.log('DOOOOCS', bourbons);
                    reply (bourbons:bourbons);
                );
            );
    
;

客户方

factory:

(function()
    'use strict';

    angular.module('hapi-auth')
        .factory('Bourbon', ['$http', function($http)

            function create(bourbon)
                return $http.post('/admin', bourbon);
            

            function all()
                return $http.get('/admin');
            

            return create:create, all:all;
        ]);
)();

控制器:

(function()
    'use strict';

    angular.module('hapi-auth')
        .controller('AdminCtrl', ['$scope', 'Bourbon', function($scope, Bourbon)
            //$scope.blog.photo = [];
            $scope.bourbon = ;
            $scope.bourbons = [];

            Bourbon.all().then(function(res)
                $scope.bourbons = res.data.bourbons;
                console.log(res.data.bourbons);
            );

            $scope.createBourbon = function(bourbon)
                console.log('BOURBB', bourbon);
                Bourbon.create(bourbon).then(function(res)
                    console.log('bourboonnnn', res.data);
                    $scope.bourbons.push(res.data);

                );
            ;


        ]);
)();

玉:

.row
   .small-4.columns
   .small-4.columns
      .review
         .insertContainer(ng-repeat='bourbon in bourbons')
            .adminName Name: bourbon.name
            img.bourbonImg(src='bourbon.photo')
            .adminBlog bourbon.blog.slice(0,200) ...
   .small-4.columns

试图在页面刷新时停止重复波旁威士忌集合中的项目.... 不确定我是否需要在这里实现某种替换方法..现在有点卡住了..

这是控制器/聚合函数中的控制台日志返回的内容:

DOOOOCS [  name: 'woodford reserve',
    location: 'kentucky',
    distillery: 'woodford',
    blog: 'fjkd;asdljfkld;ksdfj',
    __v: 0,
    comments: [],
    photo: 'http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg',
    bourbonId: '54c2aa5556267e0000b5618c',
    avgRating: 0 ,
   name: 'woodford reserve',
    location: 'kentucky',
    distillery: 'woodford',
    blog: 'fjkd;asdljfkld;ksdfj',
    __v: 0,
    comments: [],
    photo: 'http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg',
    bourbonId: '54c2aa5556267e0000b5618c',
    avgRating: 0  ]

每当运行此函数时,它似乎都会复制 Bourbons 集合中的每个项目...,它在页面刷新时作为角度控制器中的 Bourbon.all 运行。

这是集合中的波旁威士忌,在它通过聚合之前:


    "_id" : ObjectId("54c2aa5556267e0000b5618c"),
    "name" : "woodford reserve",
    "location" : "kentucky",
    "distillery" : "woodford",
    "blog" : "fjkd;asdljfkld;ksdfj",
    "comments" : [],
    "photo" : "http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg",
    "__v" : 0


更新的翡翠/追踪者:

.row
   .small-4.columns
   .small-4.columns
      .review
      .insertContainer(ng-repeat='bourbon in bourbons | unique: bourbon.bourbonId | filter: query')

            .adminName Name: bourbon.name
            img.bourbonImg(src='bourbon.photo')
            .adminBlog bourbon.blog.slice(0,200) ...
   .small-4.columns

这允许项目在第一次加载时显示,但在任何刷新/重新加载时,我现在收到此错误:

Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: bourbon in bourbons track by bourbon.bourbonId | filter:query, Duplicate key: 54c2aa5556267e0000b5618c, Duplicate value: "name":"woodford reserve","location":"kentucky","distillery":"woodford","blog":"fjkd;asdljfkld;ksdfj","__v":0,"comments":[],"photo":"http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg","bourbonId":"54c2aa5556267e0000b5618c","avgRating":0
http://errors.angularjs.org/1.3.8/ngRepeat/dupes?p0=bourbon%20in%20bourbons…C%22bourbonId%22%3A%2254c2aa5556267e0000b5618c%22%2C%22avgRating%22%3A0%7D
    at http://localhost:7070/vendor/angular/angular.js:63:12
    at ngRepeatAction (http://localhost:7070/vendor/angular/angular.js:24483:21)
    at Object.$watchCollectionAction [as fn] (http://localhost:7070/vendor/angular/angular.js:14092:13)
    at Scope.$digest (http://localhost:7070/vendor/angular/angular.js:14225:29)
    at Scope.$apply (http://localhost:7070/vendor/angular/angular.js:14488:24)
    at done (http://localhost:7070/vendor/angular/angular.js:9646:47)
    at completeRequest (http://localhost:7070/vendor/angular/angular.js:9836:7)
    at XMLHttpRequest.requestLoaded (http://localhost:7070/vendor/angular/angular.js:9777:9)

这些是在浏览器控制台中返回的波旁威士忌项目。它们都具有相同的 bourbonId,从索引 0 开始。唯一过滤器现在返回 2 个 bourbon 对象(原始对象和重复对象之一?)而不是所有对象...:

[对象,对象,对象,对象,对象]0: Object$$hashKey: "object:6"v: 0avgRating: 4blog: "fjkd;asdljfkld;ksdfj"bourbonId: "54c2aa5556267e0000b5618c"cmets: Array [0] 酒厂:“伍德福德”位置:“肯塔基”名称:“伍德福德保护区”照片:“http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg”__proto:对象 1:对象__v:0avgRating:4blog:“fjkd;asdljfkld;ksdfj”bourbonId:“ 54c2aa5556267e0000b5618c"cmets: Array[0]distillery: "woodford"location: "kentucky"name: "woodford reserve" photo: "http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg"proto: Object2: Object$$hashKey: "object: 7"v: 0avgRating: 0blog: "fjkd;asdljfkld;ksdfj"bourbonId: "54c2aa5556267e0000b5618c"cmets: Array[0]length: 0__proto: Array[0]distillery: "woodford"location: "kentucky “名称:“伍德福德保护区”照片:“http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg”proto:Object3:Object__v:0avgRating:0blog:“fjkd;asdljfkld;ksdfj”bourbonId:“54c2aa5556267e0000b5618c”cmets:数组[0]长度:0__proto__:数组[0]酒厂:“伍德福德”位置:“肯塔基州”名称:“伍德福德保护区”照片o: "http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg"proto: Object4: Object__v: 0avgRating: 0blog: "fjkd;asdljfkld;ksdfj"bourbonId: "54c2aa5556267e0000b5618c"cmets: Array[0]length: 0__proto__: Array[0]酿酒厂:“伍德福德”位置:“肯塔基”名称:“伍德福德保护区”照片:“http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg”proto:对象长度:5__proto__:Array[0]


我认为我已将其缩小为服务器端的问题,在上面列出的控制器/聚合中。我需要找到一种方法来替换更新的文档,而不是每次在客户端/浏览器上调用/运行 Bourbon.all 时都创建一个新文档……现在尝试解决它。任何提示,非常感谢。

【问题讨论】:

add ng-repeat='bourbon in bourbons track by id id 将是您对象的唯一键。 谢谢。我只是在调查:bennadel.com/blog/… 使用ng-repeat='bourbon in bourbons track by bourbon.bourbonId' 应该可以工作 我会再试一次,但这就是我正在做的,以接收上面评论中的错误。它第一次显示,然后在 refresh / reload 时出现重复错误。 最后一次试试这个ng-repeat='bourbon in bourbons track by $index' 【参考方案1】:

这似乎是服务器端的问题,通过 $index 添加轨道将解决问题。

ng-repeat='bourbon in bourbons track by $index

但问题是,它会显示重复的记录。

最好使用 AngularUI angular.unique filter

首先从链接添加 JS,然后在应用依赖项中添加“ui.filters”模块。

ng-repeat='bourbon in bourbons | unique:'bourbonId'

希望这能解决您的问题。

谢谢。

【讨论】:

我试过这个,我试过 findAndModify.. 还没有工作。 findAndModify 给了我一个找不到方法 findAndModify ,但是根据我从文档中了解到的,它应该内置在 mongoose / mongodb 中。 这个独特的过滤器无论如何都应该可以工作..你是否在你的应用程序中包含了 js github.com/angular-ui/angular-ui-OLDREPO/blob/master/modules/… 和相关模块'ui.filters' 我使用了 angular-ui-utils,它似乎包含一个独特的过滤器。我会试试那个。 好的,我取出了 $index,唯一过滤器似乎正在工作......有点......仍然允许 1 个重复...... 每次我刷新时,它都会添加一个重复的对象,当前 - 有 4 个重复项。使用独特的过滤器、原始节目和 1 个重复节目,而不是像以前一样的所有重复节目。当我重新启动服务器时,它会删除重复项..所以我猜它正在被放入浏览器存储中......?不知道它是如何工作的..【参考方案2】:

这似乎只是一个过于字面化的例子。您最终会在每个请求上得到重复的输出,因为这就是结果来自的商店的范围。

所以不要这样:

'use strict';

var Bourbon = require('../../../models/bourbon'),
    Comment = require('../../../models/comment'),
    DataStore = require('nedb'),
    db = new DataStore(),          // <-- globally scoped in the module :(
    async = require('async');

module.exports = 
    description: 'Get Bourbons',
    notes: 'Get Bourbons',
    tags: ['bourbons'],
    handler: function(request, reply)

        async.series(
            [
                function(callback)

宁可这样做:

'use strict';

var Bourbon = require('../../../models/bourbon'),
    Comment = require('../../../models/comment'),
    DataStore = require('nedb'),
    async = require('async');

module.exports = 
    description: 'Get Bourbons',
    notes: 'Get Bourbons',
    tags: ['bourbons'],
    handler: function(request, reply)

        db = new DataStore();   // <--- Init store within request scope :)

        async.series(
            [
                function(callback)

【讨论】:

不知道该笑还是该哭.. 谢谢。旅程仍在继续。

以上是关于聚合函数在页面刷新时复制 ng-repeat 中的项目。需要弄清楚如何停止重复。 Angularjs Mongodb mongoose的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS 使用控制器中的函数从服务中返回数据以用于 ng-repeat

来自 WebApi2 response.data 的 Angular ng-repeat 刷新

如何在加载我的 html 页面时调用 JavaScript 函数? [复制]

在 HTML 中的页面刷新时强制页面滚动位置到顶部

jQuery实现发送验证码30s倒计时,且刷新页面时有效

Angular.js - ng-repeat 不显示更新的数组