TODO: This function is really slow when there are a lot of UIDs to filter, for e.g. when used in `has(name)`. We could potentially have a query level cache, which can be used to speed things up a bit. Or, try to reduce the number of UIDs which make it here.
(arg funcArgs)
| 1698 | // `has(name)`. We could potentially have a query level cache, which can be used to speed things up |
| 1699 | // a bit. Or, try to reduce the number of UIDs which make it here. |
| 1700 | func (qs *queryState) filterStringFunction(arg funcArgs) error { |
| 1701 | if glog.V(3) { |
| 1702 | glog.Infof("filterStringFunction. arg: %+v\n", arg.q) |
| 1703 | defer glog.Infof("Done filterStringFunction") |
| 1704 | } |
| 1705 | attr := arg.q.Attr |
| 1706 | uids := algo.MergeSorted(arg.out.UidMatrix) |
| 1707 | var values [][]types.Val |
| 1708 | filteredUids := make([]uint64, 0, len(uids.Uids)) |
| 1709 | lang := langForFunc(arg.q.Langs) |
| 1710 | |
| 1711 | // This iteration must be done in a serial order, because we're also storing the values in a |
| 1712 | // matrix, to check it later. |
| 1713 | // TODO: This function can be optimized by having a query specific cache, which can be populated |
| 1714 | // by the handleHasFunction for e.g. for a `has(name)` query. |
| 1715 | for _, uid := range uids.Uids { |
| 1716 | vals, err := qs.getValsForUID(attr, lang, uid, arg.q.ReadTs) |
| 1717 | switch { |
| 1718 | case err == posting.ErrNoValue: |
| 1719 | continue |
| 1720 | case err != nil: |
| 1721 | return err |
| 1722 | } |
| 1723 | |
| 1724 | var strVals []types.Val |
| 1725 | for _, v := range vals { |
| 1726 | // convert data from binary to appropriate format |
| 1727 | strVal, err := types.Convert(v, types.StringID) |
| 1728 | if err != nil { |
| 1729 | continue |
| 1730 | } |
| 1731 | strVals = append(strVals, strVal) |
| 1732 | } |
| 1733 | if len(strVals) > 0 { |
| 1734 | values = append(values, strVals) |
| 1735 | filteredUids = append(filteredUids, uid) |
| 1736 | } |
| 1737 | } |
| 1738 | |
| 1739 | filtered := &pb.List{Uids: filteredUids} |
| 1740 | filter := stringFilter{ |
| 1741 | funcName: arg.srcFn.fname, |
| 1742 | funcType: arg.srcFn.fnType, |
| 1743 | lang: lang, |
| 1744 | } |
| 1745 | |
| 1746 | switch arg.srcFn.fnType { |
| 1747 | case hasFn: |
| 1748 | // Dont do anything, as filtering based on lang is already |
| 1749 | // done above. |
| 1750 | case ngramFn: |
| 1751 | filter.tokens = arg.srcFn.tokens |
| 1752 | filter.match = defaultMatch |
| 1753 | filter.tokName = "ngram" |
| 1754 | filtered = matchStrings(filtered, values, &filter) |
| 1755 | case fullTextSearchFn: |
| 1756 | filter.tokens = arg.srcFn.tokens |
| 1757 | filter.match = defaultMatch |
no test coverage detected