不要怂,就是干,撸起袖子干!

Commit de3a7360 by Mick Hansen

Merge pull request #1333 from sequelize/include-performance-optimizations

Include performance optimizations
2 parents faabcf97 3c71d152
......@@ -655,16 +655,7 @@ module.exports = (function() {
validateIncludedElements.call(this, options)
}
if (options.includeNames) {
options.includeNames = options.includeNames.concat(options.includeNames.map(function (key) {
return key.slice(0,1).toLowerCase() + key.slice(1)
}))
}
var self = this
, instance = new this.DAO(values, options)
return instance
return new this.DAO(values, options)
}
DAOFactory.prototype.create = function(values, fieldsOrOptions) {
......@@ -1343,6 +1334,7 @@ module.exports = (function() {
options.includeMap[include.as] = include
options.includeNames.push(include.as)
options.includeNames.push(include.as.substr(0,1).toLowerCase() + include.as.substr(1))
if (include.association.isMultiAssociation || include.hasMultiAssociation) options.hasMultiAssociation = true
if (include.association.isSingleAssociation || include.hasSingleAssociation) options.hasSingleAssociation = true
......
......@@ -230,7 +230,14 @@ module.exports = (function() {
// Queries with include
} else if (this.options.hasJoin === true) {
results = groupJoinData(results, this.options)
results = groupJoinData(results, {
daoFactory: this.callee,
includeMap: this.options.includeMap,
includeNames: this.options.includeNames
}, {
checkExisting: this.options.hasMultiAssociation
})
result = results.map(function(result) {
return this.callee.build(result, {
isNewRecord: false,
......@@ -328,26 +335,46 @@ module.exports = (function() {
]
*/
var groupJoinData = function(data, options) {
// includeOptions are 'level'-specific where options is a general directive
var groupJoinData = function(data, includeOptions, options) {
var results = []
, existingResult
, calleeData
, child
, calleeDataIgnore = ['__children']
, parseChildren = function(result) {
_.each(result.__children, function (children, key) {
result[key] = groupJoinData(children, (includeOptions.includeMap && includeOptions.includeMap[key]), options)
})
delete result.__children
},
primaryKeyAttribute
// Identify singular primaryKey attribute for equality check (if possible)
if (includeOptions.daoFactory.primaryKeyAttributes.length === 1) {
primaryKeyAttribute = includeOptions.daoFactory.primaryKeyAttributes[0]
} else if (includeOptions.daoFactory.rawAttributes.id) {
primaryKeyAttribute = 'id'
}
if (options.includeNames) {
calleeDataIgnore = calleeDataIgnore.concat(options.includeNames)
// Ignore all include keys on main data
if (includeOptions.includeNames) {
calleeDataIgnore = calleeDataIgnore.concat(includeOptions.includeNames)
}
data.forEach(function (row) {
row = Dot.transform(row)
calleeData = _.omit(row, calleeDataIgnore)
existingResult = _.find(results, function (result) {
if (calleeDataIgnore) {
return Utils._.isEqual(_.omit(result, calleeDataIgnore), calleeData)
// If there are :M associations included we need to see if the main result of the row has already been identified
existingResult = options.checkExisting && _.find(results, function (result) {
// If we can, detect equality on the singular primary key
if (primaryKeyAttribute) {
return result[primaryKeyAttribute] === calleeData[primaryKeyAttribute]
}
return Utils._.isEqual(result, calleeData)
// If we can't identify on a singular primary key, do a full row equality check
return Utils._.isEqual(_.omit(result, calleeDataIgnore), calleeData)
})
if (!existingResult) {
......@@ -357,24 +384,32 @@ module.exports = (function() {
for (var attrName in row) {
if (row.hasOwnProperty(attrName)) {
// Child if object, and is an child include
child = Object(row[attrName]) === row[attrName] && options.includeMap && options.includeMap[attrName]
child = Object(row[attrName]) === row[attrName] && includeOptions.includeMap && includeOptions.includeMap[attrName]
if (child) {
if (!existingResult.__children) existingResult.__children = {}
if (!existingResult.__children[attrName]) existingResult.__children[attrName] = []
// Make sure nested object is available
if (!existingResult.__children) {
existingResult.__children = {}
}
if (!existingResult.__children[attrName]) {
existingResult.__children[attrName] = []
}
existingResult.__children[attrName].push(row[attrName])
}
}
}
// parseChildren in same loop if no duplicate values are possible
if (!options.checkExisting) {
parseChildren(existingResult)
}
})
results.forEach(function (result) {
_.each(result.__children, function (children, key) {
result[key] = groupJoinData(children, (options.includeMap && options.includeMap[key]))
})
delete result.__children
})
// parseChildren after row parsing if duplicate values are possible
if (options.checkExisting) {
results.forEach(parseChildren)
}
return results
}
......
......@@ -711,7 +711,13 @@ module.exports = (function() {
}
var sql = this.QueryGenerator.selectQuery(tableName, options, factory)
queryOptions = Utils._.extend({}, queryOptions, { include: options.include, includeNames: options.includeNames, includeMap: options.includeMap })
queryOptions = Utils._.extend({}, queryOptions, {
include: options.include,
includeNames: options.includeNames,
includeMap: options.includeMap,
hasSingleAssociation: options.hasSingleAssociation,
hasMultiAssociation: options.hasMultiAssociation
})
return queryAndEmit.call(this, [sql, factory, queryOptions], 'select')
}
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!