- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有这个端点,它是客户访问网店时的初始端点:
export const getAllProductsByCategory = async (req, res, next) => {
const pageSize = parseInt(req.query.pageSize);
const sort = parseInt(req.query.sort);
const skip = parseInt(req.query.skip);
const { order, filters } = req.query;
const { brands, tags, pricesRange } = JSON.parse(filters);
try {
const aggregate = Product.aggregate();
aggregate.lookup({
from: 'categories',
localField: 'categories',
foreignField: '_id',
as: 'categories'
});
aggregate.match({
productType: 'product',
available: true,
categories: {
$elemMatch: {
url: req.params
}
}
});
aggregate.lookup({
from: 'tags',
let: { tags: '$tags' },
pipeline: [
{
$match: {
$expr: { $in: ['$_id', '$$tags'] }
}
},
{
$project: {
_id: 1,
name: 1,
slug: 1
}
}
],
as: 'tags'
});
aggregate.lookup({
from: 'brands',
let: { brand: '$brand' },
pipeline: [
{
$match: {
$expr: { $eq: ['$_id', '$$brand'] }
}
},
{
$project: {
_id: 1,
name: 1,
slug: 1
}
}
],
as: 'brand'
});
if (brands.length > 0) {
const filterBrands = brands.map((_id) => utils.toObjectId(_id));
aggregate.match({
$and: [{ brand: { $elemMatch: { _id: { $in: filterBrands } } } }]
});
}
if (tags.length > 0) {
const filterTags = tags.map((_id) => utils.toObjectId(_id));
aggregate.match({ tags: { $elemMatch: { _id: { $in: filterTags } } } });
}
if (pricesRange.length > 0 && pricesRange !== 'all') {
const filterPriceRange = pricesRange.map((_id) => utils.toObjectId(_id));
aggregate.match({
_id: { $in: filterPriceRange }
});
}
aggregate.facet({
tags: [
{ $unwind: { path: '$tags' } },
{ $group: { _id: '$tags', tag: { $first: '$tags' }, total: { $sum: 1 } } },
{
$group: {
_id: '$tag._id',
name: { $addToSet: '$tag.name' },
total: { $addToSet: '$total' }
}
},
{
$project: {
name: { $arrayElemAt: ['$name', 0] },
total: { $arrayElemAt: ['$total', 0] },
_id: 1
}
},
{ $sort: { total: -1 } }
],
brands: [
{ $unwind: { path: '$brand' } },
{
$group: {
_id: '$brand._id',
name: { $first: '$brand.name' },
slug: { $first: '$brand.slug' },
total: {
$sum: 1
}
}
},
{ $sort: { name: 1 } }
],
pricesRange: [
{
$bucket: {
groupBy: {
$cond: {
if: { $ne: ['$onSale.value', true] },
then: '$price',
else: '$sale.salePrice'
}
},
boundaries: [0, 20.01, 50.01],
default: 'other',
output: {
count: { $sum: 1 },
products: { $push: '$_id' }
}
}
}
],
products: [
{ $skip: (skip - 1) * pageSize },
{ $limit: pageSize },
{
$project: {
_id: 1,
images: 1,
onSale: 1,
price: 1,
quantity: 1,
slug: 1,
sale: 1,
sku: 1,
status: 1,
title: 1,
brand: 1,
tags: 1,
description: 1
}
},
{ $sort: { [order]: sort } }
],
total: [
{
$group: {
_id: null,
count: { $sum: 1 }
}
},
{
$project: {
count: 1,
_id: 0
}
}
]
});
aggregate.addFields({
total: {
$arrayElemAt: ['$total', 0]
}
});
const [response] = await aggregate.exec();
if (!response.total) {
response.total = 0;
}
res.status(httpStatus.OK);
return res.json(response);
} catch (error) {
console.log(error);
return next(error);
}
};
如果没有应用过滤器,所有产品都可以毫无问题地匹配请求的类别。
我的问题是当客户选择一个品牌或标签时,该方面返回产品,但只返回一个品牌/标签(因为过滤的产品只有这个品牌,所以应该如此)。
为了保留所有品牌/标签并让用户选择多个品牌/标签,我必须做什么?如果客户选择品牌,则标签应与退回的产品标签相匹配,反之亦然。
是否有更好的方法在 $facet
中实现 tags
阶段,因为 tags 是一个数组,所需的输出是:[{_id: 123, name : {label: 'test', value: 123]}]
请求是这样的:(1,2,3,4代表_id)
http://locahost:3000/get-products/?filters={brands: [1, 2], tags: [3,4], pricesRange:[]}
更新
这是带有标签
和品牌
的产品
架构:
brand: {
ref: 'Brand',
type: Schema.Types.ObjectId
},
tags: [
{
ref: 'Tags',
type: Schema.Types.ObjectId
}
]
标签
架构:
{
metaDescription: {
type: String
},
metaTitle: {
type: String
},
name: {
label: {
type: String,
index: true
},
value: {
type: Schema.Types.ObjectId
},
},
slug: {
type: String,
index: true
},
status: {
label: {
type: String
},
value: {
default: true,
type: Boolean
}
}
}
brands
架构:
description: {
default: '',
type: String
},
name: {
required: true,
type: String,
unique: true
},
slug: {
type: String,
index: true
},
status: {
label: {
default: 'Active',
type: String
},
value: {
default: true,
type: Boolean
}
}
场景:
用户访问商店,选择一个类别,所有匹配的产品都应返回匹配的brands
、tags
、priceRange
和分页。
案例 1:
用户点击复选框中的品牌
,然后请求返回匹配的产品
、标签
和priceRanges
以及所选类别的所有品牌,而不是匹配产品的所有品牌
案例二:
用户像案例 1 一样选择了一个 brand
,但随后决定也检查一个 tag
,那么请求应该返回所有 brand
和 tags
,但 products
与它们匹配。
案例三:
用户没有选择brand
但只选择了一个tag
,请求应该返回所有匹配的product
有那个/多个标签并返回与返回产品相匹配的品牌
。
案例 4:
与情况 3 相同,但用户在选择 tag/tags
后选择了 brand
,请求应返回匹配的 products
,品牌
& 标签
。
在所有情况下,分页应该返回正确的总计,priceRanges
也应该与返回的结果相匹配。
我希望现在一切都清楚了,我想我没有遗漏任何其他案例。我可能会变灰/禁用与前端响应不匹配的标签/品牌,但我不知道这是否对用户友好。
最佳答案
这是我最终得到的:
export const getAllProductsByCategory = async (req, res, next) => {
const pageSize = parseInt(req.query.pageSize);
const sort = parseInt(req.query.sort);
const skip = parseInt(req.query.skip);
const { order, filters } = req.query;
const { brands, tags, pricesRange } = JSON.parse(filters);
try {
const aggregate = Product.aggregate();
aggregate.lookup({
from: 'categories',
localField: 'categories',
foreignField: '_id',
as: 'categories'
});
aggregate.match({
productType: 'product',
available: true,
categories: {
$elemMatch: {
url: `/${JSON.stringify(req.params['0']).replace(/"/g, '')}`
}
}
});
aggregate.lookup({
from: 'tags',
let: { tags: '$tags' },
pipeline: [
{
$match: {
$expr: { $in: ['$_id', '$$tags'] }
}
},
{
$project: {
_id: 1,
name: 1,
slug: 1
}
}
],
as: 'tags'
});
aggregate.lookup({
from: 'brands',
let: { brand: '$brand' },
pipeline: [
{
$match: {
$expr: { $eq: ['$_id', '$$brand'] }
}
},
{
$project: {
_id: 1,
name: 1,
slug: 1
}
}
],
as: 'brand'
});
const filterBrands = brands.map((_id) => utils.toObjectId(_id));
const filterTags = tags.map((_id) => utils.toObjectId(_id));
const priceRanges = pricesRange ? pricesRange.match(/\d+/g).map(Number) : '';
aggregate.facet({
tags: [
{ $unwind: { path: '$brand' } },
{ $unwind: { path: '$tags' } },
{
$match: {
$expr: {
$and: [
filterBrands.length ? { $in: ['$brand._id', filterBrands] } : true
]
}
}
},
{ $group: { _id: '$tags', tag: { $first: '$tags' }, total: { $sum: 1 } } },
{
$group: {
_id: '$tag._id',
name: { $addToSet: '$tag.name' },
total: { $addToSet: '$total' }
}
},
{
$project: {
name: { $arrayElemAt: ['$name', 0] },
total: { $arrayElemAt: ['$total', 0] },
_id: 1
}
},
{ $sort: { name: 1 } }
],
brands: [
{ $unwind: { path: '$brand' } },
{ $unwind: { path: '$tags' } },
{
$match: {
$expr: {
$and: [
filterTags.length ? { $in: ['$tags._id', filterTags] } : true
]
}
}
},
{
$group: {
_id: '$brand._id',
name: { $first: '$brand.name' },
slug: { $first: '$brand.slug' },
total: {
$sum: 1
}
}
},
{ $sort: { name: 1 } }
],
products: [
{ $unwind: { path: '$brand', preserveNullAndEmptyArrays: true } },
{ $unwind: { path: '$tags', preserveNullAndEmptyArrays: true } },
{
$match: {
$expr: {
$and: [
filterBrands.length ? { $in: ['$brand._id', filterBrands] } : true,
filterTags.length ? { $in: ['$tags._id', filterTags] } : true,
pricesRange.length
? {
$and: [
{
$gte: [
{
$cond: {
if: { $ne: ['$onSale.value', true] },
then: '$price',
else: '$sale.salePrice'
}
},
priceRanges[0]
]
},
{
$lte: [
{
$cond: {
if: { $ne: ['$onSale.value', true] },
then: '$price',
else: '$sale.salePrice'
}
},
priceRanges[1]
]
}
]
}
: true
]
}
}
},
{ $skip: (skip - 1) * pageSize },
{ $limit: pageSize },
{
$project: {
_id: 1,
brand: 1,
description: 1,
images: 1,
onSale: 1,
price: 1,
quantity: 1,
sale: 1,
shipping: 1,
sku: 1,
skuThreshold: 1,
slug: 1,
status: 1,
stock: 1,
tags: 1,
title: 1
}
},
{ $sort: { [order]: sort } }
],
pricesRange: [
{ $unwind: { path: '$brand', preserveNullAndEmptyArrays: true } },
{ $unwind: { path: '$tags', preserveNullAndEmptyArrays: true } },
{
$match: {
$expr: {
$and: [
filterBrands.length ? { $in: ['$brand._id', filterBrands] } : true,
filterTags.length ? { $in: ['$tags._id', filterTags] } : true
]
}
}
},
{
$project: {
price: 1,
onSale: 1,
sale: 1,
range: {
$cond: [
{
$and: [
{
$gte: [
{
$cond: {
if: { $ne: ['$onSale.value', true] },
then: '$price',
else: '$sale.salePrice'
}
},
0
]
},
{
$lte: [
{
$cond: {
if: { $ne: ['$onSale.value', true] },
then: '$price',
else: '$sale.salePrice'
}
},
20
]
}
]
},
'0-20',
{
$cond: [
{
$and: [
{
$gte: [
{
$cond: {
if: { $ne: ['$onSale.value', true] },
then: '$price',
else: '$sale.salePrice'
}
},
20
]
},
{
$lte: [
{
$cond: {
if: { $ne: ['$onSale.value', true] },
then: '$price',
else: '$sale.salePrice'
}
},
50
]
}
]
},
'20-50',
'50+'
]
}
]
}
}
},
{
$group: {
_id: '$range',
count: { $sum: 1 }
}
},
{
$project: {
_id: 0,
range: '$_id',
count: 1
}
},
{ $unwind: { path: '$range', preserveNullAndEmptyArrays: true } },
{
$sort: {
range: 1
}
}
],
total: [
{ $unwind: { path: '$brand', preserveNullAndEmptyArrays: true } },
{ $unwind: { path: '$tags', preserveNullAndEmptyArrays: true } },
{
$match: {
$expr: {
$and: [
filterBrands.length ? { $in: ['$brand._id', filterBrands] } : true,
filterTags.length ? { $in: ['$tags._id', filterTags] } : true,
pricesRange.length
? {
$and: [
{
$gte: [
{
$cond: {
if: { $ne: ['$onSale.value', true] },
then: '$price',
else: '$sale.salePrice'
}
},
priceRanges[0]
]
},
{
$lte: [
{
$cond: {
if: { $ne: ['$onSale.value', true] },
then: '$price',
else: '$sale.salePrice'
}
},
priceRanges[1]
]
}
]
}
: true
]
}
}
},
{
$group: {
_id: null,
count: { $sum: 1 }
}
},
{
$project: {
count: 1,
_id: 0
}
}
]
});
aggregate.addFields({
total: {
$arrayElemAt: ['$total', 0]
}
});
const [response] = await aggregate.exec();
if (!response.total) {
response.total = 0;
}
res.status(httpStatus.OK);
return res.json(response);
} catch (error) {
console.log(error);
return next(error);
}
};
关于javascript - Mongo/mongoose $facet 过滤器,如果客户应用过滤器,则返回所有产品的品牌/标签作为响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58451805/
我完全迷失在链接和 Solr 术语的世界中。我目前有一个日期字段,但如果可能的话,我想“进一步”面对它。 一个例子: 字段:日期 领域:语言 所以如果我运行这个查询: http://host:port
有没有办法通过属性的值为 null 或空字符串来过滤命中? 即,向我展示所有没有作者的对象 facetFilters=作者:空 facetFilters=作者:'' 或者将其包含在 OR 值列表中?
C++ 标准库中有一些标准基类方面,其默认行为依赖于经典的“C”语言环境 (std::locale::classic())。如果您的程序需要特定于文化的功能,那么切换到派生类方面(又名 byname
使用这个 SO solution我创建了一个包含两个“空”图的 facet,目的是与另一组 facet_wrap 图组合,如下所示。目的是为不同的单位测量设置两个 y 轴标签。如何使网格布局看起来像顶
我在 SOLR 索引中存储了大量文档。我想执行一个查询,返回指定字段的 Facet 计数,并返回每个 Facet 字段 的前 100 个文档。 例如。假设我的 SOLR 索引中存储了一堆书。 { na
我使用 Solr 4.7.0 有一个大约 500 万个文档的 Solr 索引,大小为 8GB。我需要在 Solr 中分组,但发现它太慢了。下面是组配置: group=on group.facet=on
Elasticsearch Histogramfacet似乎不支持 all_terms = true(即:即使 count=0 也返回 facetvalue/bucket) 这是正确的吗? 最佳答案
有$facet自 3.4 以来 mongo 中的聚合阶段 -这个很酷。它允许在同一个输入文档集的单个阶段内处理多个聚合管道。 但它不允许在另一个 $facet 中使用一个 $facet。引用:“任何其
我在 solr 中使用 Stats 组件来获取分面统计数据,效果很好,现在我有兴趣对我的日期字段执行相同的操作。但是在统计模块中使用 facet.date 字段似乎不起作用,有没有办法让它工作? 我的
我正在尝试将多个图与方面对齐。我的问题有点小但很烦人:我可以制作一个绘图,以便绘图区域对齐并且刻面本身对齐,但是刻面条的宽度并不完全相同。如果刻面的标签长度不同,则刻面条的大小将调整为使文本适合刻
我在 R 中有一个数据框,我想在分面 ggplot 条形图中绘制它。 我在 ggplot 中使用此代码: ggplot(data_long, aes(x = partei, y = wert, fil
我在 Eclipse Java EE IDE 中有一个面向 Web 开发人员的 Maven 项目。但是当我启用 JPA 方面时,我无法选择 JPA(没有 JPA 选项)。我是否忘记包含一些依赖项? 我
我使用 ggplot 绘制了一个分面图这是情节 我的问题是,刻面(标签)按字母顺序排序(例如:E1、E10、E11、E13、E2、E3、I1、I10、I2)但我需要它们是像 E1、I1、E2 这样的自
我正在尝试在 Intellij IDEA 14 中运行播放框架应用程序。 我安装了 Scala 插件并需要所有 jar 文件。 但是在 Project-Structure -> Facet 中,我在添
我正在使用命令 qplot(factor(ww), WeeklyYield, geom = "bar", fill = I("grey50"))+facet_wrap(~model+name) 为 m
最近我发现了 python 可视化库“Facets”,想知道我是否可以离线生成 html 输出。 我正在使用 chrome 浏览器和 webcomponents-lite.js不需要。 另外,我在我的
我正在测试可用在 https://www.primefaces.org/showcase/ui/overlay/dialog/loginDemo.xhtml 的 PrimeFaces 示例.我在 Ec
我想在solr响应的过滤查询(fq)中传递逗号分隔的值,当前,当我想传递多个类别时,我使用OR运算符。 像这样fq = categoryId:3 OR categoryId:55 OR categor
我有以下 Elasticsearch 映射 { "mappings": { "hotel": { 'properties': {"name": {
我正在尝试从 solr 获取字段的唯一值。我已经使用facet来获取字段值。我的方面查询参数看起来像 - SolrQuery query = new SolrQuery();
我是一名优秀的程序员,十分优秀!