J'essaie d'obtenir un décompte distinct d'une colonne particulière en utilisant Sequelize. Ma première tentative utilise la méthode "count" de mon modèle, mais cela ne semble pas possible.
La fonction DISTINCT est nécessaire car je joins d'autres tables et filtre les lignes du parent en fonction des tables associées.
voici la requête que j'aimerais:
SELECT COUNT(DISTINCT Product.id) as `count`
FROM `Product`
LEFT OUTER JOIN `Vendor` AS `vendor` ON `vendor`.`id` = `Product`.`vendorId`
WHERE (`vendor`.`isEnabled`=true );
en utilisant la requête suivante sur mon modèle de produit:
Product.count({
include: [{model: models.Vendor, as: 'vendor'}],
where: [{ 'vendor.isEnabled' : true }]
})
Génère la requête suivante:
SELECT COUNT(*) as `count`
FROM `Product`
LEFT OUTER JOIN `Vendor` AS `vendor` ON `vendor`.`id` = `Product`.`vendorId`
WHERE (`vendor`.`isEnabled`=true );
Il semble que cela soit désormais pris en charge dans les versions 1.7.0+ de Sequelize.
les méthodes count
et findAndCountAll
d'un modèle vous donneront un compte "réel" ou "distinct" de votre modèle parent.
MISE À JOUR: Nouvelle version
Comme mentionné dans les commentaires, les choses ont changé depuis mon post d'origine. Il existe désormais des options distinct
et col
distinctes. Les documents pour distinct
indiquent:
Appliquer COUNT (DISTINCT (col)) sur la clé primaire ou sur options.col.
Il semble que vous vouliez maintenant quelque chose comme:
MyModel.count({
include: ...,
where: ...,
distinct: true,
col: 'Product.id'
})
.then(function(count) {
// count is an integer
});
Message d'origine
Après avoir regardé méthode Model.count dans lib/model.js et tracé du code, j'ai constaté que lorsque vous utilisez Model.count
, Vous pouvez simplement ajouter tout type d'arguments de fonction d'agrégation pris en charge par MYSQL à votre objet d'options. Le code suivant vous donnera le nombre de valeurs différentes dans MyModel
's someColumn
:
MyModel.count({distinct: 'someColumn', where: {...}})
.then(function(count) {
// count is an integer
});
Ce code génère efficacement une requête de ce type: SELECT COUNT(args) FROM MyModel WHERE ...
, où args
sont toutes les propriétés de l'objet options qui ne sont pas réservées (telles que DISTINCT
, LIMIT
etc).
la documentation Sequelize sur count
renvoie à ne méthode de comptage qui ne vous permet pas de spécifier la colonne pour obtenir le nombre de valeurs distinctes:
Model.prototype.count = function(options) {
options = Utils._.clone(options || {});
conformOptions(options, this);
Model.$injectScope(this.$scope, options);
var col = '*';
if (options.include) {
col = this.name + '.' + this.primaryKeyField;
expandIncludeAll.call(this, options);
validateIncludedElements.call(this, options);
}
Utils.mapOptionFieldNames(options, this);
options.plain = options.group ? false : true;
options.dataType = new DataTypes.INTEGER();
options.includeIgnoreAttributes = false;
options.limit = null;
options.offset = null;
options.order = null;
return this.aggregate(col, 'count', options);
};
Fondamentalement SELECT COUNT(DISTINCT(*))
ou SELECT COUNT(DISTINCT(primaryKey))
si vous avez défini une clé primaire.
Pour faire l'équivalent Sequelize de SELECT category, COUNT(DISTINCT(product)) as 'countOfProducts' GROUP BY category
, vous feriez:
model.findAll({
attributes: [
'category',
[Sequelize.literal('COUNT(DISTINCT(product))'), 'countOfProducts']
],
group: 'category'
})