You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongoose:嵌套数组查找更新及采购产品关联实现问询

Solution for Purchase Pre-Processing Logic with Mongoose Schemas

Hey there! I'll walk you through a solid implementation for your requirement—creating a product first, then linking a purchase to its transaction array while handling nested array operations. Let's start with your existing schemas for reference:

Your Existing Schemas

// Purchases Schema
const purchasesSchema = new Schema({
  date: String,
  status: String,
  product: { type: Schema.Types.ObjectId, ref: 'Product' }
});

// Product Schema
const productSchema = new Schema({
  product_name: String,
  transaction: [{ price: Number, purchase: { type: Schema.Types.ObjectId, ref: 'Purchases' } }]
});

// Define models
const Purchase = mongoose.model('Purchases', purchasesSchema);
const Product = mongoose.model('Product', productSchema);

Step 1: Create the Product First

First, we need to ensure the product exists before creating any purchase linked to it. Here's how to create a product instance (with optional duplicate checks):

async function createProduct(productName) {
  try {
    // Check if product already exists to avoid duplicates (adjust based on your needs)
    let product = await Product.findOne({ product_name: productName });
    if (!product) {
      product = new Product({ product_name: productName });
      await product.save();
      console.log('Product created successfully:', product);
    }
    return product;
  } catch (err) {
    console.error('Error creating product:', err);
    throw err;
  }
}

Once the product exists, we'll create the purchase record, then update the product's transaction array to include the new transaction with a reference to the purchase. Use a Mongoose transaction to ensure both operations succeed or fail together—this prevents data inconsistency if one step fails.

async function createPurchaseAndLinkToProduct(productId, purchaseData, transactionPrice) {
  const session = await mongoose.startSession();
  session.startTransaction();

  try {
    // 1. Create the purchase record, linking it to the target product
    const purchase = new Purchase({
      date: purchaseData.date,
      status: purchaseData.status,
      product: productId
    });
    await purchase.save({ session });

    // 2. Update the product's transaction array with the new linked entry
    const updatedProduct = await Product.findByIdAndUpdate(
      productId,
      {
        $push: {
          transaction: {
            price: transactionPrice,
            purchase: purchase._id // Link the newly created purchase to the transaction
          }
        }
      },
      { new: true, session } // Return the updated product and use the transaction session
    );

    await session.commitTransaction();
    session.endSession();

    console.log('Purchase created and linked successfully:', purchase);
    console.log('Updated product with transaction:', updatedProduct);
    return { purchase, updatedProduct };
  } catch (err) {
    await session.abortTransaction();
    session.endSession();
    console.error('Error creating purchase and linking:', err);
    throw err;
  }
}

Step 3: Retrieve Nested Transactions & Linked Purchases

To fetch a product with fully populated transaction and purchase details, use Mongoose's nested populate method:

async function getProductWithFullTransactions(productId) {
  try {
    const product = await Product.findById(productId)
      .populate({
        path: 'transaction.purchase',
        model: 'Purchases' // Populate the full purchase data for each transaction entry
      });
    return product;
  } catch (err) {
    console.error('Error fetching product with transactions:', err);
    throw err;
  }
}

Key Notes

  • Atomicity with Transactions: Transactions are critical here—they ensure that if either the purchase creation or product update fails, no partial changes are saved to the database.
  • Uniqueness: Consider adding a unique index on product_name in the Product schema if you want to enforce unique product names at the database level.
  • Flexibility: Adjust the createProduct function's duplicate check logic based on your business rules (e.g., skip checks if duplicate product names are allowed).

内容的提问来源于stack exchange,提问作者Pengguna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:59:21