【问题标题】:Adding array of objects to mongodb issue将对象数组添加到 mongodb 问题
【发布时间】:2020-05-11 03:55:15
【问题描述】:

我在向 mongodb 添加对象数组时遇到问题。问题与我收到帖子 ngOnInit() 的时间有关,并且在我开始向邀请组添加任何内容之前有一个像这样的 _id 条目

如果我添加 this.inviteGroup = [] 以摆脱 _id 第一个条目,那么我可以成功地将我的邀请添加到数据库中,就像这张图片一样。有没有办法不拥有与我的猫鼬模式相关的 _id? 但是很自然地 this.inviteGroup = [] 可以做到,所以我一次只能有一个条目,因为它会擦除页面加载时的所有内容。我怎样才能使那个 _id 条目不再存在,以便当我执行 .push() 时它不会导致页面重新加载,因为它会抛出 .push()。我想为每个邀请在 db 中有多个条目。是我的猫鼬模型有问题吗?感谢您的帮助!

猫鼬模式定义

 inviteGroup: {
    bidderId: { type: String, lowercase: true, trim: true },
    username: { type: String, lowercase: true, trim: true }
  }

app.js

app.patch("/api/listings/:id", (req, res) => {
  console.log("INVITE GRdddOUP IS");
  console.log(req.body);
  console.log(req.body[0].biddingUserId);
  let invites;
  if (req.body[0].biddingUserId) {
    invites = req.body;
    console.log("INVITE IS");
  }
  console.log(invites);
  if (invites) {
    console.log("INVITE GROUP IS");
    console.log(req.params.id);
    Post.findByIdAndUpdate(
      { _id: req.params.id },
      {
        inviteGroup: invites
      },
      function(err, docs) {
        if (err) {
          console.log(err);
          res.json(err);
        } else {
          return true;
          console.log(docs);
        }
      }
    );

组件.ts

import {
  Component,
  OnInit,
  ViewChild,
  OnDestroy,
  AfterViewInit
} from "@angular/core";
import { Router } from "@angular/router";
import {
  MatTableDataSource,
  MatPaginator,
  MatSort,
  MatDialog
} from "@angular/material";
import { NgForm, FormControl } from "@angular/forms";
import { SubmitListingService } from "../submit-listing/submit-auction.service";
import { BidderInvite } from "./bidder-invite.model";
import { Observable, Subject } from "rxjs";
import { startWith, map, takeUntil } from "rxjs/operators";
import { Page } from "ngx-pagination/dist/pagination-controls.directive";
import { BidderInviteRetrieved } from "./bidder-invite-retrieved";
@Component({
  selector: "app-private-auction-invite",
  templateUrl: "./private-auction-invite.component.html",
  styleUrls: ["./private-auction-invite.component.css"]
})
export class PrivateAuctionInviteComponent
  implements OnInit, AfterViewInit, OnDestroy {
  allMyPeopleAreInvited: boolean;
  auctionId: string;
  dataSource: MatTableDataSource<any> = new MatTableDataSource();
  timeout: any = null;
  posts: BidderInviteRetrieved[];
  artistId: string;
  bidderId: string;
  inviteGroup: BidderInvite[] = [];
  test: any[] = [];
  value: string;
  usernameFound: string;
  userSearched: string;
  invites: BidderInvite[] = [];
  destroy = new Subject();
  inviteName: string;
  filteredOptions: Observable<string[]>;
  myControl = new FormControl();
  selectedValue: string;

  url: string;
  displayedColumnsInvites: string[] = ["User", "revokeInvite"];
  options: string[] = [];

  @ViewChild(MatSort, { static: false }) set sort(sort: MatSort) {
    this.dataSource.sort = sort;
  }

  @ViewChild(MatPaginator, { static: false }) set paginator(
    paginator: MatPaginator
  ) {
    this.dataSource.paginator = paginator;
  }

  constructor(
    private router: Router,
    private submitListingService: SubmitListingService
  ) {}

  ngOnInit() {
    this.inviteGroup = [];
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
    this.allMyPeopleAreInvited = false;
    this.url = this.router.url;
    const value = this.router.url.split("/");

    this.auctionId = value[2];
    this.artistId = value[3];


    this.submitListingService
      .getPrivateAuctionInviteList(this.auctionId)
      .pipe(takeUntil(this.destroy))
      .subscribe(res => {
        this.inviteGroup = res.posts;
        console.log("res");
        console.log(res);
        console.log(this.inviteGroup);

        if (this.inviteGroup["_id"].length > 2) {
          this.inviteGroup = [];
          console.log(this.inviteGroup);
        }
      });

    this.filteredOptions = this.myControl.valueChanges.pipe(
      startWith(""),
      map(value => this._filter(value))
    );
  }
  ngAfterViewInit() {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;

    this.dataSource = new MatTableDataSource(this.inviteGroup);

    this.dataSource.data = this.inviteGroup;
  }

  sendInvite(form: NgForm) {
    if (form.invalid) {
      return;
    }

    let counter: number;
    counter = 0;
    console.log("USER " + this.value);
    console.log("POST LEGNTH: " + this.posts.length);
    for (let i = 0; i < this.posts.length; i++) {
      counter = counter++;
      console.log("post");
      console.log(form.value.username);

      let user = this.posts[i].username.trim().toLowerCase();
      let enteredUser = form.value.username.trim().toLowerCase();
      console.log("COUNTER LOOP NUMBER: " + counter);


      if (enteredUser === user) {
        this.bidderId = this.posts[i].id;
        console.log(this.inviteGroup);

        let invites = this.inviteGroup;
        console.log("INVITE LENGTH =  " + this.inviteGroup.length);
        console.log(invites.indexOf);
        this.inviteGroup.push({
          biddingUserId: this.bidderId,
          username: this.posts[i].username
        });

        console.log(this.inviteGroup);
        console.log("invite group");
        console.log(this.inviteGroup);
        //this.posts = [];

        this.dataSource.data = this.inviteGroup;
        console.log("invite group");
      }
    }

    console.log("BIDDER ID " + this.bidderId);
    if (this.bidderId === null || this.bidderId === undefined) {
      console.log("SOMETHING WENT WRONG");
    }
    console.log("made it to next section");

    let invites = this.inviteGroup;
    console.log("invites[0].username");


    console.log("filtering....");

    invites = invites.filter((obj, pos, arr) => {
      return (
        arr.map(mapObj => mapObj["bidderId"]).indexOf(obj["bidderId"]) === pos
      );
    });

    console.log("invites");
    console.log(invites);
    this.submitListingService
      .sendPrivateAuctionInvite(this.auctionId, invites)
      .pipe(takeUntil(this.destroy))
      .subscribe(res => {
        console.log("res");
        console.log(res);
      });
  }

  private onKeySearch(event: any) {
    console.log("EVENT IS ");
    console.log(event);

    clearTimeout(this.timeout);
    var $this = this;
    this.timeout = setTimeout(function() {
      if (event.keyCode !== 13) {
        $this.executeListing(event.target.value);
      }
    }, 1000);
  }

  private executeListing(bidderName: string) {
    console.log("BIDDERNAME");
    console.log(bidderName);
    if (bidderName === "[Object object]") {
      return;
    }
    if (bidderName.length < 4) {
      return;
    }
    if (bidderName.length > 3) {
      this.submitListingService
        .getUserIdAutoComplete(bidderName)
        .pipe(takeUntil(this.destroy))
        .subscribe(res => {
          console.log("res");
          console.log(res);
          this.posts = res.posts;
          console.log(this.posts);

          //   this.artists = res.posts;
        });
    }
  }
  private _filter(value: string): string[] {
    const filterValue = value.toLowerCase();

    return this.options.filter(
      option => option.toLowerCase().indexOf(filterValue) === 0
    );
    console.log("OPTION IS " + filterValue);
  }
  storeUserPrivaeAuctionInvite(user: Page) {
    console.log("USER VALUE I S" + user);
  }

  ngOnDestroy() {
    this.destroy.next();
    this.destroy.complete();
  }
}

角度服务

 sendPrivateAuctionInvite(id: string, inviteGroup1: BidderInvite[]) {

   // console.log(inviteGroup1);
    return this.http.patch(
      `http://localhost:3000/api/listings/${id}/`,
      inviteGroup1
    );
  }

BidderInvite 模型

export interface BidderInvite {
  biddingUserId: string;
  username: string;
}

【问题讨论】:

    标签: node.js angular mongodb express mongoose


    【解决方案1】:

    如果我理解你的问题,问题与更新方法缺少运算符有关。

    当你使用类似的东西时:

    Post.findByIdAndUpdate(
      { _id: req.params.id },
      {
        inviteGroup: invites // <-- Update statement
      },
      function(err, docs) {
        //...
      }
    );
    

    它将替换inviteGroup 字段的完整值。

    要将项目添加到数据库中的现有数组中,您需要使用$push$addToSet 运算符,以及$each 运算符。

    $push$addToSet 运算符每次只添加/追加一个项目,因此必须使用 $eachinvites 数组中存在的每个项目进行交互。在以下示例中,我将包括它,因为我相信这是您需要的。但是,请花时间阅读每个运算符的链接文档,以便找到更多示例。

    $push 运算符将指定的值附加到数组中,如果添加的值已存在于字段中,则不会进行额外的验证。如:

    //document on mongodb, before the update
    // { _id : "1", inviteGroup : [] }
    
    
    //Invites from the request
    // invites = [ { bidderId:"5e2350c7f88cfb331c4f67de", username:"artist1"} ];
    
    //update method
    Post.findByIdAndUpdate(
      { _id: req.params.id }, //req.params.id = "1"
      { $push : { inviteGroup: { $each : invites } } },
      function(err, docs) {
        //...
      }
    );
    
    //document on mongodb, after the update
    /*
    {
      _id : "1",
      inviteGroup : [ { bidderId:"5e2350c7f88cfb331c4f67de", username:"artist1"} ]
    }
    */
    

    如果你用相同的值再次调用更新方法:

    Post.findByIdAndUpdate(
      { _id: req.params.id }, //req.params.id = "1"
      { $push : { inviteGroup: { $each : invites } } },
      function(err, docs) { }
    );
    
    // the end document will be like:
    /*
    {
      _id : "1",
      inviteGroup : [
        { bidderId:"5e2350c7f88cfb331c4f67de", username:"artist1"},
        { bidderId:"5e2350c7f88cfb331c4f67de", username:"artist1"}
      ]
    }
    */
    

    以同样的方式,$addToSet 运算符将一个值添加到数组中,除非该值已经存在,在这种情况下,$addToSet 对该数组没有任何作用。喜欢:

    //document on mongodb, before the update
    // { _id : "1", inviteGroup : [] }
    
    
    //Invites from the request
    // invites = [ { bidderId:"5e2350c7f88cfb331c4f67de", username:"artist1"} ];
    
    
    //update method
    Post.findByIdAndUpdate(
      { _id: req.params.id }, //req.params.id = "1"
      { $addToSet : { inviteGroup: { $each : invites } } },
      function(err, docs) {
        //...
      }
    );
    
    //document on mongodb, after the update
    /*
    {
      _id : "1",
      inviteGroup : [ { bidderId:"5e2350c7f88cfb331c4f67de", username:"artist1"} ]
    }
    */
    

    如果你用相同的值再次调用更新方法:

    Post.findByIdAndUpdate(
      { _id: req.params.id }, //req.params.id = "1"
      { $addToSet : { inviteGroup: { $each : invites } } },
      function(err, docs) { }
    );
    
    //the end document will be the same because the same value was already on the list:
    /*
    {
      _id : "1",
      inviteGroup : [ { bidderId:"5e2350c7f88cfb331c4f67de", username:"artist1"} ]
    }
    */
    

    嗯,我希望这就是你要找的。 =]

    【讨论】:

      【解决方案2】:

      您的架构定义应该是:

       inviteGroup: {
          type: [inviteSchema]
          default: undefined //if you want to unset [] 
       }
      
       invite: {
          bidderId: { type: String, lowercase: true, trim: true },
          username: { type: String, lowercase: true, trim: true }
        }
      

      (见https://mongoosejs.com/docs/schematypes.html#arrays

      尝试缓存以防止重新加载。 (见https://github.com/isaacs/node-lru-cache)和How to stop MongoDB from reloading data every time I refresh a page?

      尝试在带有_id: 0 的查询输出中排除_id。见https://docs.mongodb.com/v3.2/tutorial/project-fields-from-query-results/#return-all-but-the-excluded-field

      【讨论】:

      • 投影解决了我的问题。谢谢!
      【解决方案3】:

      试试这个。希望对你有帮助。

          Post.findByIdAndUpdate(
                { _id: req.params.id },
                {
                  inviteGroup: invites
                },
                {select: {_id: 0}}, // sets the document fields to return
                function(err, docs) {
                  if (err) {
                    console.log(err);
                    res.json(err);
                  } else {
                    return true;
                    console.log(docs);
                  }
                }
              );
      

      【讨论】:

      • 只有在我不注释掉 this.inviteGroup = []; 时才会起作用,因为如果它被注释掉,那么当我 .push() 进入时,第一个 JSON 控制台图像中的 ._id 将导致页面重新加载JSON 对象。但这导致我们在 mongodb 中一次仍然只有一个条目,因为 this.inviteGroup = [] 每次都在页面加载时清除结果,所以我不能将下一个邀请附加到对象。它将每次都推入一个空对象而不是追加。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-10
      • 2021-11-06
      • 2019-12-03
      • 2020-10-01
      • 2015-06-17
      • 1970-01-01
      • 2022-01-24
      相关资源
      最近更新 更多