{
  "source_file": "0930",
  "source_platform": "个人博客",
  "author": "Eugene Yan",
  "title_listed": "Search: Query Matching via Lexical, Graph, and Embedding Methods",
  "keywords": "搜索,查询匹配,嵌入",
  "domain": "机器学习",
  "content_type": "深度技术解析",
  "is_paid_flag": "否",
  "url": "https://eugeneyan.com/writing/search-query-matching/",
  "publish_date": "2021-04",
  "corpus_stage": "推理部署",
  "notes": "搜索查询匹配方法综述",
  "id": "7b4da3876c27",
  "collected_at": "2026-10-02T14:17:12",
  "title": "Search: Query Matching via Lexical, Graph, and Embedding Methods",
  "body_markdown": "eugeneyan\nStart Here\nWriting\nSpeaking\nPrototyping\nAbout\nSearch: Query Matching via Lexical, Graph, and Embedding Methods\n[\nteardown\nmachinelearning\nproduction\n🔥\n]\n· 21 min read\nSearch and recommendations have a lot in common. They help users learn about new products, and need to retrieve and rank millions of products in a very short time (<150ms). They’re trained on similar data, have content and behavioral-based approaches, and optimize for engagement (e.g., click-through rate) and revenue (e.g., conversion, gross merchandise value).\nNonetheless, search differs in one key aspect—it has the user’s query as additional input.\n(Think of search as recommendations with the query as extra context.) This is a boon and a bane. It’s a boon because the query provides more context to help us help users find what they want; it’s a bane because users expect results to be in line with their query.\nIn this post, we’ll explore various ways to normalize, rewrite, and retrieve (aka match) documents using\nthe query\n. (Though the ranking step is also important, we’ll focus on query processing and matching for now). We’ll compare three main approaches:\nLexical-based\n: This approach replaces or augments the query string directly via normalization, spellchecks, expansion, translation, etc.\nGraph-based\n: This uses a knowledge graph is used to understand queries and documents at a higher level for query expansion and matching.\nEmbedding-based\n: This uses latent representations—learned via self-supervised or supervised techniques—for expansion and matching.\nLexical-based: The bedrock of query processing\nLexical-based approaches start with\npreprocessing\nthe query string. This includes normalization (e.g., stemming, unicode standardization, removing accents), spell checking, and tokenization. Stemming in particular helps to reduce the various morphological forms of words to the same query. For example, “hiking boot” and “hike boots” are\nstemmed\nto “hike boot”, making it easier for downstream matching of queries to documents. In general, these preprocessing steps replace the query.\nQuery expansion\naugments the query by adding tokens to match additional documents. Additional tokens include synonyms (e.g., “handphone” can be expanded to “handphone OR mobile phone OR cellphone”) and abbreviations (e.g., “t-shirt L” can be expanded to “t-shirt L OR t-shirt large”).\nQuery relaxation\nis somewhat the opposite of query expansion; we remove tokens from the query instead. This makes the query less restrictive and increases recall. The simplest approach is to remove stop words. For product search, query relaxation can drop color, measure (e.g., small, medium, large), model numbers, brand, and other entities.\nFor example, “acme gold iphone charger i012e large” can be relaxed to “iphone charger”. Trying to match on the full query string leads to no results. But in this case, we can infer that the key intent is “iphone charger” and relax the query string to increase recall. The example below also shows “charger” being rewritten to “charging”, as well as query expansion by adding the “apple” token.\nAn example of query rewriting, relaxation, and expansion\nQuery translation\nis another form of rewriting, where a text-translation paradigm is applied to convert tail (i.e., unpopular, 20th percentile) queries into head queries that account for the bulk of traffic, helping to increase recall. It also helps in downstream ranking as we have more behavioral information (e.g., clicks, purchases) on head queries.\nAfter the query is processed, it can be used to\nretrieve relevant documents\n. For lexical approaches, it mostly involves matching tokens and n-grams in the query to document fields such as title, description, category, attributes, etc.\nDoorDash’s search system\nstarts with basic processing\n(e.g., removing extra whitespaces, lowercasing, expanding contractions) before spell correction via the\nSymmetric Delete\nspelling correction algorithm. Then, the updated query tokens are standardized via a manually curated synonym dictionary. For example, “Poulet Frit Kentucky”, “KFZ”, and “KFC” are normalized to “kfc”.\nHowever, specific—and valid—queries such as “Chick’n” were being spell-corrected to “Chicken”. (There are many items in their catalog with names that might not be present in an English dictionary and have low edit distance to regular words.) To avoid these invalid corrections, they apply spell check only after the initial attempt at matching does not return any results.\nMy spellchecker wanted to replace \"Chick'n\" too\nYahoo shared about their text-translation approach\nto rewrite queries. The intent was to overcome the problem of matching and ranking cold start queries (not seen in the click log). To achieve this, they built a translation model using query-document pairs from their bipartite click graph. (A bipartite graph is a graph where nodes can be separated into two, disjointed sets, such as queries and documents.) The translation model learns phrase-level translations such as word alignment, phrase extraction, and phrase scoring. At query time, the model segments each query into phrases and then translates each phrase.\nAn example of Yahoo's bipartite query-document graph (\nsource\n)\nEach query is typically translated into hundreds of candidates. Candidates are scored on three groups of features: query features (e.g., number of tokens in query, number of stop words, language model score), translated query features (same as query features), and similarity between the original query and translated query (e.g.,\nJaccard similarity\nbetween shared URLs, word-level cosine similarity, etc). The similarity features were found to be the most important.\nFinally, the original query and top-scoring translated query are both used to retrieve documents. The final result set is a union of documents matching either query. For documents that match both queries, their max score is used.\nGraph-based: Adding concepts and relationships\nGraph-based approaches involve building and using a\nknowledge graph to expand queries and improve retrieval\n. The most famous example of a knowledge graph is probably Google’s,\nintroduced\nalmost 10 years ago. It has nodes for people, places, things, etc, and edges to connect them together. This is how Google provides search result summaries, sometimes leading to interesting findings.\nGoogle's knowledge graph powers result summaries (\nsource\n)\nDuring query time, the query is parsed and tagged to the relevant concepts (i.e., nodes) in the knowledge graph. The query can then be expanded—to include relevant concepts—by finding the closest nodes in the knowledge graphs.\nBuilding a knowledge graph is taxing. Nonetheless, we can bootstrap one by using\nWordNet\n, a lexical database of semantic relationships between words (available in more than 200 languages!) or\nConceptNet\n, a semantic network where edges are assertions of commonsense between concepts (e.g., “is a”, “is used for”, “is made of”). Another approach is to mine\nWikipedia redirects\n.\nConceptNet with synonym, part of, and form of relationships (\nsource\n)\nUber shared about how they use a knowledge graph for search\n.\nFirst, they developed an ontology to describe the entities of the graph and the relationships between them. For example, foods and cuisines are related by\ncountryOfOrigin\nwhile each entity can be a\nsubCategoryOf\nanother entity.\nThen, they ingest and transform data from multiple sources to fit their ontology. Next, entities and edges are deduplicated, and new edges are built across multiple data sources. For example, the same restaurant on Foursquare and internal data should be represented as the same node. This connects disparate restaurant data from multiple sources via the same node—looking up a restaurant should return metadata from all data sources.\nThen, they annotate restaurants and menu items with tags based on graph nodes—this is done offline. During query time (i.e., online), queries are annotated and expanded—by traversing the graph—in real-time to increase recall.\nFor example, if a user queries for “Asian”, the graph expands the search to include subsets such as “Chinese” and “Japanese”. Similarly, a query for “Udon” can be expanded to include related terms such as “Ramen”, “Soba”, and “Japanese”. The graph also includes location as an edge. Thus, if a restaurant is outside a user’s delivery zone, the graph can traverse to find similar cuisines in the user’s area.\nUber's knowledge graph with\ncountryOfOrigin\nand\nsubCategoryOf\nrelationships (\nsource\n)\nDoorDash also uses a knowledge graph\nand shared their ontology. They have three types of entities (i.e., nodes) in their knowledge graph (which is implemented in Neo4j):\nStore\n: Where the food is sold. It has the\n_biz\nsuffix (e.g.,\nihop_biz\n).\nFood category\n: A coarse-grained descriptor of foods such as Chicken, Chinese, Fast Food. It has the\n_cat\nsuffix (e.g.,\nbreakfast_cat\n).\nFood tag\n: A fine-grained descriptor of popular items sold, such as fried chicken, dim sum, tacos. It has the\n_tag\nsuffix (e.g,\nsandwich_tag\n).\nEntities are connected by three types of relationships:\nEach store will belong to a primary food category. For example,\nihop_biz\nbelongs to\nbreakfast_cat\n.\nEach food category can have at most one parent food category. For example,\nsandwich_cat\nonly has\nbreakfast_cat\nas its parent, and\ndeli_cat\nonly has\nsandwich_cat\nas its parent. This enforces hierarchy between the food categories.\nEach food tag will belong to one food category. For example,\ndeli_tag\n,\nsandwich_tag\n, and\ncheesesteaks_tag\nbelong to\nsandwich_cat\n.\nDoorDash graph with relationships between stores, categories, and tags (\nsource\n)\nAt query time, the knowledge graph expands on the underlying query concept. For example, when a customer searches for “KFC”, the KFC store nearest to the customer is returned as the top result. Then, the graph is used to expand the query to return restaurants with tags (e.g.,\nfried_chicken_tag\n,\nwings_tag\n) that have the same primary category (i.e.,\nchicken_cat\n).\nQuery expansion for \"kfc\" (\nsource\n)\nSimilarly, when the customer enters a broad search query such as “Asian”, it is mapped to the\nasian_cat\n. This is then expanded to subcategories such as\nthai_cat\nand\nchinese_cat\n, and restaurants with tags belonging to these categories are retrieved. In the example below, Charm Thai contains the\nthai_tag\nwhich is part of the\nthai_cat\n, and HI Peninsula contains the\ndim_sum_tag\nwhich is part of the\nchinese_cat\n.\nQuery expansion for \"asian\" (\nsource\n)\nKnow of other knowledge graphs used in search?\nPlease let me know!\nPitfalls of lexical and graph-based approaches\nLexical-based approaches that treat each query as a bag-of-words can lead to incorrect results. DoorDash shared an example where customers searching for “California rolls” would get results for Mexican restaurants, instead of sushi places, because the tokens “California” and “roll” appear in the food menus of Mexican restaurants.\nLexical-based approaches also struggle to understand:\nHypernyms\n: Broader categories of words, such as “hat” being a hypernym of “beret”, “cap”, and “snapback”.\nSynonyms\n: Different words, same meaning (e.g., “burgundy dress”, “red dress”).\nAntonyms\n: Words which have or imply opposite meaning. While “latex gloves” contain the same tokens as “latex free gloves”, they have the opposite meaning.\nWhile this can be overcome with dictionaries and rules, it is tedious to manually curate and maintain these knowledge bases for each language.\nLexical-based approaches are also fragile to morphological variants (e.g., “woman” vs. “women”). While stemming can be applied, it is imperfect and can lead to information loss and errors. For example, “universal”, “university”, and “universe” all stem to “univers”. Similarly, this involves handcrafted rules which are a pain to create and maintain.\nFinally, lexical-based approaches are sensitive to spelling errors.\nOne out of 10 queries is misspelled\n. While we can adopt spellcheckers and correctors, as DoorDash’s experience showed, spell correctors can be too aggressive and change the customer’s intent.\nThough knowledge graphs help with increasing recall, they’re also a lot of manual work. From Uber and DoorDash’s experience, effort is needed to build the ontology, populate the knowledge graph with data from multiple sources, deduplicate nodes and edges, create new edges for better relationship mapping, and ensure the accuracy of nodes and edges.\nThen, we need to tag catalog items with the nodes in the knowledge graphs offline, and tag and expand queries in real-time online. Knowledge graphs are costly to scale and maintain, and require constant manual curation and quality checks to ensure correctness.\nTo augment lexical and graph-based approaches, teams have increasingly turned to representation learning and embedding-based approaches.\nEmbedding-based: Decomposing queries into numbers\nRepresentation learning is a way to learn latent representations (i.e., embeddings) of items from data. They are latent because they cannot be observed directly. They’re also referred to as semantic embeddings because they learn the semantics of items well. It can be done\nvia self-supervised or supervised methods\n.\nThe most commonly known self-supervised approach is probably\nword2vec\n, which learns text embeddings given a corpus of text. It does this by training a network to predict a word’s neighbors (i.e., context) given a word via the skip-gram approach, or predict a word given its neighbors via the continuous-bag-of-words (CBOW) approach. A similar paradigm can be used to generate query embeddings.\nSupervised methods usually use click or purchase events as labels. This involves training a model that takes a query and document as input and predicts the probability of click or purchase. The trained model is then used to generate query and document embeddings.\nOnce we have query and document embeddings, we can use them in query expansion and document retrieval. Embeddings have several advantages over the lexical-based approach. For example, they encode semantics and eliminate the need for a synonym dictionary; “handphone”, “cellphone”, and “mobile phone” are likely to be close in the embedding space. Furthermore, with character-level n-grams, query embeddings can be made less sensitive to morphological variants and spelling errors.\nSelf-supervised techniques: No need for labels!\nYahoo’s approach to learning representations\nstarts with creating a\nbipartite graph\nof queries and clicked documents. Then, they extracted tokens from co-clicked queries to represent documents; tokens from more co-clicked queries are likely to be more representative of documents. Thus, the more queries two documents share, the closer they are, and vice versa. Similarly, queries that share many co-clicked documents are likely to have similar intent.\nEach query is represented by a vector of tokens, with weights proportional to their frequencies in the query, and normalized to 1. Then, query and document vectors are propagated iteratively (somewhat like\nalternating least squares\nfor collaborative filtering), resulting in query and document embeddings in the same vector space. To get similarities between queries and documents, they compute the inner product of these vectors.\nUber used the GloVe algorithm\nto learn query embeddings. GloVe (Global Vectors) creates word embeddings by learning word co-occurrence in a corpus. To apply the language modeling paradigm to search, each query is considered a word in a sentence, and queries are “next to each other” in the sentence (i.e., same context) if both queries lead to an order from the same restaurant. To put it another way, the restaurant is the context and two queries share the same context if they both lead to orders in the same restaurant.\nQueries leading to orders from the same restaurant have the same context (\nsource\n)\nThey start with constructing a Pointwise Mutual Information matrix with the search queries, where\na\nand\nb\nare tuning params and\np(q1, q2)\nis the joint distribution of\nq1\nand\nq2\n.\n\\[\\operatorname{pmi}\\left(q_{1}, q_{2}\\right)=\\log \\frac{p\\left(q_{1}, q_{2}\\right)}{p\\left(q_{1}\\right)^{a} p\\left(q_{2}\\right)^{b}}\\]\nThen, they apply a GloVe-based factorization model to learn query embeddings. These query embeddings can then be used for query expansion (via approximate nearest neighbors) to improve search recall. For example, if a user searches for “tan tan noodle” (or more correctly, “dan dan noodle”) and there are no restaurants selling it nearby, it can be expanded to “Little Szechuan”, “Chinese”, and “Spicy Food”.\nQuery expansion for \"tan tan noodle\" (\nsource\n)\nGrubHub adopts a similar paradigm\nusing the skip-gram architecture and shared examples where the nearest neighbors for “Udon” and “Mediterranean” almost map 1:1 with a reference food graph. This provides assurance that the self-supervised approach can capture knowledge graph-like semantics via embeddings.\nEmbeddings for \"udon\" and \"mediterranean\" and how they compare to the knowlege graph (\nsource\n)\nSupervised techniques: Improves modeling of our desired event\nAmazon built semantic product search\nusing customer behavioral data. Their neural net architecture shares embeddings across the query and product. Queries are fed into the model as they are while products are represented as an ordered bag-of-attributes (e.g., title, brand, color). They also tried learning attribute embeddings but it led to 5% lower recall (relative to concatenating attributes), likely due to the variability in accuracy and availability of structured data.\nAmazon's neural network architecture for semantic product search (\nsource\n)\nAverage pooling is then applied to get a fixed-length embedding for the query and product. Relative to recurrent approaches such as LSTM and GRU, using average pooling made little difference (<0.5%) in mean average precision and recall@100 while requiring less computation, training time, and inference latency.\nThey initially adopted a two-part hinge loss. First,\nŷ\nis the cosine similarity between query and product embeddings, and\ny\n= 1 if the product is purchased (in response to the query) and zero otherwise. The hinge loss ensures that\nŷ\n> 0.9 when\ny\n= 1 and\nŷ\n< 0.2 when\ny\n= 0. However, they found a large overlap in score distributions between random negatives (red) and purchased positives (green) due to products that were impressed but not purchased.\nThus, they updated the two-part loss to also consider products that were impressed but not purchased, where\nŷ\n< 0.55 where\ny\n= impressed but not purchased. This improved the separation of scores between random negatives (red), impressed but not purchased negatives (grey), and purchased positives (green).\nScore distribution with two-part (left) and three-part (right) hinge loss (\nsource\n)\nTo tokenize queries and products, they applied tokenization approaches such as:\nWork unigrams and n-grams: N-grams capture phrase-level information that unigrams don’t. For example, “chocolate milk” and “milk chocolate” are different though they share the same unigrams.\nCharacter tri-grams: These are robust to types and handle compound words (e.g., “amazontv”, “firetvstick”) well. They also capture similarity of model parts.\nExample tokens for the query \"artistic iphone 6s case\" (\nsource\n)\nIt is unfeasible to have a vocabulary of all possible word n-grams as dictionary size grows exponentially with\nn\n. Thus, they maintain a vocabulary of hundreds of thousands of n-grams based on token frequency. To handle unseen words, they hash out-of-vocabulary (OOV) tokens to additional embedding bins. By using fixed hash functions and shared query-document embeddings, unseen tokens in both the query and products map to the same embedding vector. A bin size 5-10x larger than vocab size is used. Then, all tokens are combined as a single bag-of-tokens (i.e., unordered, equal weight).\nFacebook’s embedding-based search\nadopts a two-tower approach with separate towers for queries and documents. The model is formulated as a ranking problem based on distance between a query and document. Cosine similarity is used as the distance metric.\nFacebook's two-tower architecture that includes location and social features (\nsource\n)\nThey use triplet loss to approximate the recall objective. For a given triplet\n(q, d+, d-)\n,\nq\nis the query while\nd+\nand\nd-\nare the associated positive and negative documents.\nD(q, d)\nis the distance between the query and document embedding and\nm\nis the margin enforced between positive and negative pairs. The intuition is to separate the positive and negative pairs by the distance margin.\n\\[L=\\sum_{i=1}^{N} \\max \\left(0, D\\left(q^{(i)}, d_{+}^{(i)}\\right)-D\\left(q^{(i)}, d_{-}^{(i)}\\right)+m\\right)\\]\nFor positive labels, they tried using clicks and impressions. Why impressions as positive labels? The intuition is to teach the model to return the same set of results that will be ranked high by the ranker. Both were found to be equally effective, though adding impressions to click data did not improve the model.\nFor negative labels, they tried using random samples and impressed-but-not-clicked samples. The model trained on the latter (i.e., non-clicked impressions) had worse recall relative to random negatives, with a 55% recall drop for the people embedding model. (Contrast this to Amazon’s approach where accounting for non-click impressions led to improved results.) They hypothesized that non-click impressions bias towards hard cases where the documents match the query on at least one factor. In contrast, the majority of documents are easy cases that don’t match the query at all. Thus, using non-click impressions bias the training data, making it not representative of the actual retrieval task.\nFor text features, they used character and word n-grams. Adding word n-grams led to small but consistent improvements (+1.5% recall). Similar to Amazon, they found the cardinality of word n-grams too high (352 million for query trigrams) and had to apply hashing to reduce the size of the embedding table.\nAs additional context, they included location features of the query (e.g., city, country, language) and document (e.g., group location). They also included social embedding features that were trained via a separate embedding model to embed users and entities in the social graph.\nAs a final example, we look at\nJD’s semantic retrieval model\nwhich takes it one step further with the introduction of multiple query heads.\nJD's two-tower architecture with multiple query heads (\nsource\n)\nThe item tower is straightforward where embeddings from multiple attributes (e.g., title, brand, seller) are concatenated into a single vector (this is similar to Amazon’s approach though they have embeddings for each attribute). Then, the vector goes through multiple\nRectified Linear Unit\nlayers. The output item embedding is finally normalized to be the same length as the query embedding.\nThe query tower is novel in that it has multiple heads (à la\nTransformer\n). An additional projection layer passes the dense input layer into\nk\ndense representations. These\nk\nrepresentations are then passed into\nk\nseparate encoders, each with their own parameters. As a result, each query head captures different semantic meanings for a query, such as different popular brands for a product query (e.g., Apple and Samsung for “cellphone”) and different products for a brand query (e.g., phones and monitors for “Samsung”).\nTo get query-item similarity, they compute a weighted sum of all inner products between the multiple query embeddings and the single item embedding. The weights are computed from the softmax of the same set of inner products, with a temperature parameter (β). The higher the temperature, the more uniform the weights will be. As temperature goes to zero, the similarity score becomes equivalent to selecting the largest inner product.\n\\[w_{i}=\\frac{\\exp \\left(e_{i}^{\\top} g / \\beta\\right)}{\\sum_{j=1}^{m} \\exp \\left(e_{j}^{\\top} g / \\beta\\right)}\\]\nTo create negative item labels, they used a mix of random negatives and batch negatives. Random negatives are uniformly sampled from all items. Thus, each item has the same probability of showing up as a negative. However, this is computationally expensive as each random negative has to go through the item tower (to get the item embedding). Batch negatives come from the other query-item pairs in the same batch. For a query-item pair, the other positive items in the same batch are used as item negatives. They found that a proportion of 0.5 - 0.75 random negatives works well.\nUsing 50 - 75% random negatives leads to optimal results (\nsource\n)\nEmbedding-based approaches have pitfalls too\nFor example, Uber shared that “halal” may expand to “middle eastern”, “mediterranean”, or South-East Asian cuisines and retrieve restaurants that may not be halal, leading to a poor customer experience. Furthermore, representation learning requires a large amount of behavioral data that might not be available when the search system is launched in a new marketplace with little to no data.\nThus, I’ve found\nlexical, graph, and embedding-based approaches to be complementary\n. Most search systems use embedding-based approaches to augment lexical and/or graph-based approaches (instead of replacing them completely). For example:\nUber uses its knowledge graph with query embeddings for query expansion\nAmazon’s semantic matching augments keyword and behavioral matching\nFacebook’s semantic matching augments their existing boolean-matching\nAmazon's (left, semantic matching) and Facebook's (right, NN Operator in the retrieval box) embedding-based approach augmenting existing methods (\nsource\n,\nsource\n)\nConclusion: Start lexical, then embeddings\nThere’s no one way to handle search queries. Lexical-based techniques are a fundamental, content-based approach that doesn’t require building a knowledge graph or large amounts of behavioral data—if you’re building a search system from scratch, perhaps start here. ElasticSearch and Lucene largely work out of the box.\nIf you find yourself reaching the point of diminishing returns with lexical or graph-based approaches, especially with long-tail queries, try augmenting it with query embeddings learned via self-supervised representation learning—they’re bang for buck.\nAm I missing anything? Reach out and let me know!\nHow do search engines match queries to documents, people, or products?\nI studied some examples & found three methods:\n• Lexical: Rewriting, expansion, relaxation\n• Graph: Mapping to concepts & relationships\n• Embedding: Via (self-)supervised learning\nhttps://t.co/pXZVSZLQxC\n— Eugene Yan (@eugeneyan)\nApril 28, 2021\nReferences\nThings Not Strings: Understanding Search Intent with Better Recall\nRanking Relevance in Yahoo Search\nIntroducing the Knowledge Graph: things, not strings\nFood Discovery with Uber Eats: Building a Query Understanding Engine\nQuery2vec: Search query expansion with query embeddings\nSemantic Product Search\nEmbedding-based Retrieval in Facebook Search\nPersonalized and Semantic Retrieval: E-commerce Search via Embedding Learning\nTowards the Next Generation of Query-Ad Matching in Baidu’s Sponsored Search\nThanks\nto Yang Xinyi and\nDavid Golden\nfor reading drafts of this. Thanks to\nAlex Egg\nfor initial discussion on this topic.\nIf you found this useful, please cite this write-up as:\nYan, Ziyou. (Apr 2021). Search: Query Matching via Lexical, Graph, and Embedding Methods. eugeneyan.com.\n        https://eugeneyan.com/writing/search-query-matching/.\nor\n@article{yan2021query,\n  title   = {Search: Query Matching via Lexical, Graph, and Embedding Methods},\n  author  = {Yan, Ziyou},\n  journal = {eugeneyan.com},\n  year    = {2021},\n  month   = {Apr},\n  url     = {https://eugeneyan.com/writing/search-query-matching/}\n}\nShare on:\nBrowse related tags:\n[\nteardown\nmachinelearning\nproduction\n🔥\n]\nor\nSearch\n« My Impostor Syndrome Stories (Guest Post by Susan Shu)\nThe Metagame of Applying Machine Learning »\nJoin\n11,800+\nreaders getting updates on machine learning, RecSys, LLMs, and engineering.\nGet email updates",
  "metadata": {
    "title": "Search: Query Matching via Lexical, Graph, and Embedding Methods",
    "description": "An overview and comparison of the various approaches, with examples from industry search systems.",
    "keywords": null,
    "author": "Eugene Yan",
    "og:site_name": "eugeneyan.com",
    "og:title": "Search: Query Matching via Lexical, Graph, and Embedding Methods",
    "og:type": "article",
    "og:description": "An overview and comparison of the various approaches, with examples from industry search systems.",
    "og:url": "https://eugeneyan.com/writing/search-query-matching/",
    "og:image": "https://eugeneyan.com/assets/og_image/search-query-og.jpg",
    "twitter:card": "summary_large_image",
    "twitter:domain": "eugeneyan.com",
    "twitter:title": "Search: Query Matching via Lexical, Graph, and Embedding Methods",
    "twitter:description": "An overview and comparison of the various approaches, with examples from industry search systems.",
    "twitter:image": "https://eugeneyan.com/assets/og_image/search-query-og.jpg",
    "article:published_time": "2021-04-25T00:00:00+00:00",
    "article:author": "https://eugeneyan.com/about/",
    "article:section": "posts",
    "article:tag": "🔥"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/7b4da3876c27/code/body-000.txt",
      "chars": 265,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/icon-search.svg",
      "bytes": 425,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-feeb4bd87b8704a903b2.svg",
      "src": "https://eugeneyan.com/assets/icon-search.svg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/query-processing.webp",
      "bytes": 43866,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-3408f239467ce45b677b.webp",
      "src": "https://eugeneyan.com/assets/query-processing.webp",
      "alt": "An example of query rewriting, relaxation, and expansion",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/chicken-spellcheck.webp",
      "bytes": 14194,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-61095e358c4031e69039.webp",
      "src": "https://eugeneyan.com/assets/chicken-spellcheck.webp",
      "alt": "My spellchecker wanted to replace Chick'n too",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/yahoo-click-graph.webp",
      "bytes": 10308,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-55450f580eaa4362c59b.webp",
      "src": "https://eugeneyan.com/assets/yahoo-click-graph.webp",
      "alt": "Yahoo's bipartite query-document graph",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/google-kgraph.webp",
      "bytes": 30938,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-6d212e6c76662b888258.webp",
      "src": "https://eugeneyan.com/assets/google-kgraph.webp",
      "alt": "Google's knowledge graph powers result summaries",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/conceptnet.webp",
      "bytes": 18418,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-b200f5be109998a60b15.webp",
      "src": "https://eugeneyan.com/assets/conceptnet.webp",
      "alt": "An example of ConceptNet with synonym, part of, and form of relationships",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/uber-graph.webp",
      "bytes": 23356,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-a4bd36e2f57ec5835ab9.webp",
      "src": "https://eugeneyan.com/assets/uber-graph.webp",
      "alt": "Uber's knowledge graph with country-of-origin and sub-category-of relationships",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/doordash-graph.webp",
      "bytes": 32994,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-e9e4fb442063ec1ea8f5.webp",
      "src": "https://eugeneyan.com/assets/doordash-graph.webp",
      "alt": "DoorDash graph with relationships between stores, categories, and tags",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/doordash-kfc.webp",
      "bytes": 25104,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-925ab1e3919b1399c6bd.webp",
      "src": "https://eugeneyan.com/assets/doordash-kfc.webp",
      "alt": "Query expansion for 'kfc'",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/doordash-asian.webp",
      "bytes": 33674,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-b9174d0c5a157124773d.webp",
      "src": "https://eugeneyan.com/assets/doordash-asian.webp",
      "alt": "Query expansion for 'asian'",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/uber-embedding.webp",
      "bytes": 14154,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-e3a833aed0bb3000b2d0.webp",
      "src": "https://eugeneyan.com/assets/uber-embedding.webp",
      "alt": "Queries leading to orders from the same restaurant have the same context",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/uber-expansion.webp",
      "bytes": 16416,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-33d6e1ba0660b6cc7319.webp",
      "src": "https://eugeneyan.com/assets/uber-expansion.webp",
      "alt": "Query expansion for 'tan tan noodle'",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/grubhub-embedding.webp",
      "bytes": 16406,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-06f0e0bad9713073e04b.webp",
      "src": "https://eugeneyan.com/assets/grubhub-embedding.webp",
      "alt": "Embeddings for 'udon' and 'mediterranean' and how they compare to the knowlege graph",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/amazon-search-nn.webp",
      "bytes": 15350,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-1bcf1b1137979bb5be68.webp",
      "src": "https://eugeneyan.com/assets/amazon-search-nn.webp",
      "alt": "Amazon's neural network architecture for semantic product search",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/amazon-search-hinge-loss.webp",
      "bytes": 8632,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-cce58be7ac9b9b3cbd5f.webp",
      "src": "https://eugeneyan.com/assets/amazon-search-hinge-loss.webp",
      "alt": "Score distribution with two-part (left) and three-part (right) hinge loss",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/amazon-search-tokens.webp",
      "bytes": 22548,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-87be203780c2b5d404c6.webp",
      "src": "https://eugeneyan.com/assets/amazon-search-tokens.webp",
      "alt": "Example tokens for the query 'artistic iphone 6s case'",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/fb-search-nn.webp",
      "bytes": 14422,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-3bf0355bbeca09a83722.webp",
      "src": "https://eugeneyan.com/assets/fb-search-nn.webp",
      "alt": "Facebook's two-tower architecture that includes location and social features",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/jd-search-nn.webp",
      "bytes": 24084,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-7c94d278337fde0285fb.webp",
      "src": "https://eugeneyan.com/assets/jd-search-nn.webp",
      "alt": "JD's two-tower architecture with multiple query heads",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/jd-negative-mix.webp",
      "bytes": 16412,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-a966371e5e3d07d290e0.webp",
      "src": "https://eugeneyan.com/assets/jd-negative-mix.webp",
      "alt": "Using 0.5 - 0.75 random negatives leads to optimal results",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/embedding-augmentation.webp",
      "bytes": 13586,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-5c5ad72b260c1cefee79.webp",
      "src": "https://eugeneyan.com/assets/embedding-augmentation.webp",
      "alt": "Amazon's (left, semantic matching) and Facebook's (right, NN Operator in the retrieval box) embedding-based approach augmenting existing methods",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/icon-twitter.svg",
      "bytes": 892,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-0083a7581b07e5f40e7b.svg",
      "src": "https://eugeneyan.com/assets/icon-twitter.svg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/icon-linkedin.svg",
      "bytes": 559,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-f7a16c3e46e5838cec4d.svg",
      "src": "https://eugeneyan.com/assets/icon-linkedin.svg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/bluesky.svg",
      "bytes": 745,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-be754e8ecdaf6de94f55.svg",
      "src": "https://eugeneyan.com/assets/bluesky.svg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/icon-facebook.svg",
      "bytes": 1123,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-5d55b59733923cf14223.svg",
      "src": "https://eugeneyan.com/assets/icon-facebook.svg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/icon-mail.svg",
      "bytes": 841,
      "reused": false,
      "local_path": "attachments/7b4da3876c27/images/body-b179147617228dfafb9f.svg",
      "src": "https://eugeneyan.com/assets/icon-mail.svg",
      "alt": "",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [],
  "links": [
    {
      "href": "https://eugeneyan.com/",
      "label": "eugeneyan",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/start-here/",
      "label": "Start Here",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/writing/",
      "label": "Writing",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/speaking/",
      "label": "Speaking",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/prototyping/",
      "label": "Prototyping",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/about/",
      "label": "About",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/search/",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/tag/teardown/",
      "label": "teardown",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/tag/machinelearning/",
      "label": "machinelearning",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/tag/production/",
      "label": "production",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/tag/🔥/",
      "label": "🔥",
      "type": "a"
    },
    {
      "href": "https://9ol.es/porter_js_demo.html",
      "label": "stemmed",
      "type": "a"
    },
    {
      "href": "https://doordash.engineering/2020/12/15/understanding-search-intent-with-better-recall/",
      "label": "DoorDash’s search system",
      "type": "a"
    },
    {
      "href": "https://github.com/wolfgarbe/SymSpell",
      "label": "Symmetric Delete",
      "type": "a"
    },
    {
      "href": "https://www.kdd.org/kdd2016/subtopic/view/ranking-relevance-in-yahoo-search",
      "label": "Yahoo shared about their text-translation approach",
      "type": "a"
    },
    {
      "href": "https://en.wikipedia.org/wiki/Jaccard_index",
      "label": "Jaccard similarity",
      "type": "a"
    },
    {
      "href": "https://blog.google/products/search/introducing-knowledge-graph-things-not/",
      "label": "introduced",
      "type": "a"
    },
    {
      "href": "https://en.wikipedia.org/wiki/WordNet",
      "label": "WordNet",
      "type": "a"
    },
    {
      "href": "https://en.wikipedia.org/wiki/Open_Mind_Common_Sense",
      "label": "ConceptNet",
      "type": "a"
    },
    {
      "href": "https://en.wikipedia.org/wiki/Wikipedia:Redirect",
      "label": "Wikipedia redirects",
      "type": "a"
    },
    {
      "href": "https://conceptnet.io/",
      "label": "source",
      "type": "a"
    },
    {
      "href": "https://eng.uber.com/uber-eats-query-understanding/",
      "label": "Uber shared about how they use a knowledge graph for search",
      "type": "a"
    },
    {
      "href": "https://twitter.com/eugeneyan",
      "label": "Please let me know!",
      "type": "a"
    },
    {
      "href": "https://blog.google/products/search/abcs-spelling-google-search/",
      "label": "One out of 10 queries is misspelled",
      "type": "a"
    },
    {
      "href": "https://en.wikipedia.org/wiki/Word2vec",
      "label": "word2vec",
      "type": "a"
    },
    {
      "href": "http://stanford.edu/~rezab/classes/cme323/S15/notes/lec14.pdf",
      "label": "alternating least squares",
      "type": "a"
    },
    {
      "href": "https://bytes.grubhub.com/search-query-embeddings-using-query2vec-f5931df27d79",
      "label": "GrubHub adopts a similar paradigm",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/1907.00937",
      "label": "Amazon built semantic product search",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/2006.11632",
      "label": "Facebook’s embedding-based search",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/2006.02282",
      "label": "JD’s semantic retrieval model",
      "type": "a"
    },
    {
      "href": "https://en.wikipedia.org/wiki/Rectifier_(neural_networks)",
      "label": "Rectified Linear Unit",
      "type": "a"
    },
    {
      "href": "https://en.wikipedia.org/wiki/Transformer_(machine_learning_model)",
      "label": "Transformer",
      "type": "a"
    },
    {
      "href": "https://t.co/pXZVSZLQxC",
      "label": "https://t.co/pXZVSZLQxC",
      "type": "a"
    },
    {
      "href": "https://twitter.com/eugeneyan/status/1387199382223790080?ref_src=twsrc%5Etfw",
      "label": "April 28, 2021",
      "type": "a"
    },
    {
      "href": "http://research.baidu.com/Public/uploads/5d12eca098d40.pdf",
      "label": "Towards the Next Generation of Query-Ad Matching in Baidu’s Sponsored Search",
      "type": "a"
    },
    {
      "href": "https://xdg.me/",
      "label": "David Golden",
      "type": "a"
    },
    {
      "href": "https://twitter.com/eggie5",
      "label": "Alex Egg",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/writing/imposter-syndrome-susan/",
      "label": "« My Impostor Syndrome Stories (Guest Post by Susan Shu)",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/writing/machine-learning-metagame/",
      "label": "The Metagame of Applying Machine Learning »",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:52:25Z",
  "source_url": "https://eugeneyan.com/writing/search-query-matching/",
  "papers": [
    {
      "status": "ok",
      "url": "http://stanford.edu/~rezab/classes/cme323/S15/notes/lec14.pdf",
      "bytes": 202239,
      "reused": false,
      "local_path": "papers/repair/d5d0a6977e12593d7869.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1907.00937",
      "bytes": 1154424,
      "reused": false,
      "local_path": "papers/repair/0cafbe2ed69fcbe54aa8.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/2006.11632",
      "bytes": 868336,
      "reused": true,
      "local_path": "papers/repair/a4df419b898afe1f50a0.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/2006.02282",
      "bytes": 3112295,
      "reused": true,
      "local_path": "papers/repair/cd9428cc4301d92a5e7f.pdf"
    },
    {
      "status": "invalid_file_type",
      "url": "http://research.baidu.com/Public/uploads/5d12eca098d40.pdf",
      "content_type": "text/html",
      "retried_at": "2026-10-20T17:58:22Z"
    }
  ],
  "actual_video_files": [],
  "body_chars": 28172,
  "expected_body_images": 25,
  "discovery_status": "ok",
  "delivery_status": "partial",
  "missing_reason": "invalid_file_type",
  "raw_html": "attachments/7b4da3876c27/pages/source.html",
  "local_html": "attachments/7b4da3876c27/pages/article.html",
  "body_base_path": "attachments/7b4da3876c27/pages/",
  "body_markdown_path": "attachments/7b4da3876c27/pages/article.md"
}