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

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() { ...@@ -655,16 +655,7 @@ module.exports = (function() {
validateIncludedElements.call(this, options) validateIncludedElements.call(this, options)
} }
if (options.includeNames) { return new this.DAO(values, options)
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
} }
DAOFactory.prototype.create = function(values, fieldsOrOptions) { DAOFactory.prototype.create = function(values, fieldsOrOptions) {
...@@ -1343,6 +1334,7 @@ module.exports = (function() { ...@@ -1343,6 +1334,7 @@ module.exports = (function() {
options.includeMap[include.as] = include options.includeMap[include.as] = include
options.includeNames.push(include.as) 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.isMultiAssociation || include.hasMultiAssociation) options.hasMultiAssociation = true
if (include.association.isSingleAssociation || include.hasSingleAssociation) options.hasSingleAssociation = true if (include.association.isSingleAssociation || include.hasSingleAssociation) options.hasSingleAssociation = true
......
...@@ -230,7 +230,14 @@ module.exports = (function() { ...@@ -230,7 +230,14 @@ module.exports = (function() {
// Queries with include // Queries with include
} else if (this.options.hasJoin === true) { } 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) { result = results.map(function(result) {
return this.callee.build(result, { return this.callee.build(result, {
isNewRecord: false, isNewRecord: false,
...@@ -328,26 +335,46 @@ module.exports = (function() { ...@@ -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 = [] var results = []
, existingResult , existingResult
, calleeData , calleeData
, child , child
, calleeDataIgnore = ['__children'] , 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) { // Ignore all include keys on main data
calleeDataIgnore = calleeDataIgnore.concat(options.includeNames) if (includeOptions.includeNames) {
calleeDataIgnore = calleeDataIgnore.concat(includeOptions.includeNames)
} }
data.forEach(function (row) { data.forEach(function (row) {
row = Dot.transform(row) row = Dot.transform(row)
calleeData = _.omit(row, calleeDataIgnore) calleeData = _.omit(row, calleeDataIgnore)
existingResult = _.find(results, function (result) { // If there are :M associations included we need to see if the main result of the row has already been identified
if (calleeDataIgnore) { existingResult = options.checkExisting && _.find(results, function (result) {
return Utils._.isEqual(_.omit(result, calleeDataIgnore), calleeData) // 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) { if (!existingResult) {
...@@ -357,24 +384,32 @@ module.exports = (function() { ...@@ -357,24 +384,32 @@ module.exports = (function() {
for (var attrName in row) { for (var attrName in row) {
if (row.hasOwnProperty(attrName)) { if (row.hasOwnProperty(attrName)) {
// Child if object, and is an child include // 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 (child) {
if (!existingResult.__children) existingResult.__children = {} // Make sure nested object is available
if (!existingResult.__children[attrName]) existingResult.__children[attrName] = [] if (!existingResult.__children) {
existingResult.__children = {}
}
if (!existingResult.__children[attrName]) {
existingResult.__children[attrName] = []
}
existingResult.__children[attrName].push(row[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) { // parseChildren after row parsing if duplicate values are possible
_.each(result.__children, function (children, key) { if (options.checkExisting) {
result[key] = groupJoinData(children, (options.includeMap && options.includeMap[key])) results.forEach(parseChildren)
}) }
delete result.__children
})
return results return results
} }
......
...@@ -711,7 +711,13 @@ module.exports = (function() { ...@@ -711,7 +711,13 @@ module.exports = (function() {
} }
var sql = this.QueryGenerator.selectQuery(tableName, options, factory) 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') 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!