Home > Blockchain >  How to match field value and populate (virtual) from foreign document in mongoose.js?
How to match field value and populate (virtual) from foreign document in mongoose.js?

Time:07-02

I have two different schemas.

const BookSchema = mongoose.Schema(
  {
    uuid: { type: String, required: true, unique: true },
    name: {
      type: String,
      required: true,
    },
  },
  { timestamps: true }
);

BookSchema.virtual("listing", {
  ref: "Listing",
  localField: "_id",
  foreignField: "book",
  justOne: true,
  // Tried adding this to check listing data with value isDeleted: false in Listing
  // But it actually returns doc of BookSchema
  match: (doc) => {
    return doc;
  },
});

const BookModal = mongoose.model("Book", BookSchema);
const ListingSchema = mongoose.Schema(
  {
    book: { type: mongoose.Schema.Types.ObjectId, ref: "Book"},
    price: { type: Number, required: true },
    listingId: { type: String, unique: true },
    listingDate: { type: String, default: `${Date.now()}` },
    isDeleted: { type: Boolean, default: false },
    deletedAt: { type: Date, default: null },
  },
  { timestamps: true }
);

const ListingModal = mongoose.model("Listing", BookSchema);

Let consider having following documents:

UserCollection
-----
[{
    _id: "665zadas99",
    uuid: "22ac",
    name: "book 1",
  }, {
    _id: "776abebt00",
    uuid: "12se",
    name: "book 2",
}]

ListingCollection
-----

[{
    _id: "123hdysak23",
    book: "665zadas99",  // referencing book 1
    price: 100,
    listingId: "1",
    listingDate: "16021828",
    isDeleted: true,
    deletedAt: "2022-01-01",
}, {
    _id: "654hska67",
    book: "665zadas99", // referencing book 1
    price: 300,
    listingId: "2",
    listingDate: "16031345",
    isDeleted: false,
    deletedAt: null,
}, {
    _id: "479vaia67",
    book: "776abebt00", // matching book 2
    price: 300,
    listingId: "3",
    listingDate: "16031345",
    isDeleted: true,
    deletedAt: "2022-01-01",
}]

Now when I query and populate the listing as,

BookModal.find().populate("listing")

I expect to get the following result: The books should only populate the data from the listings collection if the listing is not deleted.

[{
    _id: "665zadas99",
    uuid: "22ac",
    name: "book 1",
    listing: {
        _id: "654hska67",
        book: "665zadas99",
        price: 300,
        listingId: "2",
        listingDate: "16031345",
        isDeleted: false,
        deletedAt: null,
    }
  }, {
    _id: "776abebt00",
    uuid: "12se",
    name: "book 2",
}]

Current Output:

[{
    _id: "665zadas99",
    uuid: "22ac",
    name: "book 1",
    listing: {
      _id: "123hdysak23",
      book: "665zadas99",
      price: 100,
      listingId: "1",
      listingDate: "16021828",
      isDeleted: true,
      deletedAt: "2022-01-01",
    }
  }, {
    _id: "776abebt00",
    uuid: "12se",
    name: "book 2",
    listing: {
      _id: "479vaia67",
      book: "776abebt00",
      price: 300,
      listingId: "3",
      listingDate: "16031345",
      isDeleted: true,
      deletedAt: "2022-01-01",
    }
}]

Is it possible to attain this with the usage of population method and not using aggregations/other methods?

CodePudding user response:

You can use basic query selector, the document is there if you want to do additional logic with the document that is currently populated:

BookSchema.virtual("listing", {
  ref: "Listing",
  localField: "_id",
  foreignField: "book",
  justOne: true,
  match: { isDeleted: false }
});
  • Related